Java: альтернатива BufferedReader
У меня проблемы с BufferedWriter
/BufferedReader
,
По сути, всякий раз, когда я пытаюсь прочитать файл с BufferedReader.readLine()
он читает все до символа новой строки (т.е. символ новой строки опускается).
Например:
String temp;
File f = new File(path.toURI());
BufferedReader reader = new BufferedReader(new FileReader(f));
while ((temp = reader.readLine()) != null) {
//Work with temp
}
Я знаю о существовании BufferedReader#newLine()
, но похоже, что он не получает точно новую строку (разделитель?), которая ранее была опущена.
Из моего понимания, если бы я прочитал следующее:
abcd\n
efgh\r\n
ijkl\r
Он вернется:
abcd\n
efgh\n
ijkl\n
Я спрашиваю, есть ли класс, который может читать символы, не пропуская их как BufferedInputStream
, сохраняя при этом способность читать строки как BufferedReader#readLine()
3 ответа
\n
это linux/unix
окончание строки \r\n
является windows
конец строки.
если есть такой файл, у которого обе строки заканчиваются, его следует переформатировать.
Мое предложение будет, если вы когда-нибудь сталкивались с таким файлом, просто переформатируйте его, чтобы использовать \n
или же \r\n
(в зависимости от вашей ОС не то, что это имеет значение в настоящее время). это делает вашу жизнь проще, так что жизнь следующего человека, который будет использовать его дальше.
В качестве альтернативы (пожалуйста, не используйте это:/) вы можете переопределить BufferReader.readLine(Boolean b)
к этому:
String readLine(boolean ignoreLF) throws IOException {
StringBuffer s = null;
int startChar;
synchronized (lock) {
ensureOpen();
boolean omitLF = ignoreLF || skipLF;
bufferLoop:
for (;;) {
if (nextChar >= nChars)
fill();
if (nextChar >= nChars) { /* EOF */
if (s != null && s.length() > 0){
if(skipLF=='\r'){
return s.toString() + "\r\n";
}else{
return s.toString() + "\n";
}
}
else
return null;
}
boolean eol = false;
char c = 0;
int i;
/* Skip a leftover '\n', if necessary */
if (omitLF && (cb[nextChar] == '\n'))
nextChar++;
skipLF = false;
omitLF = false;
charLoop:
for (i = nextChar; i < nChars; i++) {
c = cb[i];
if ((c == '\n') || (c == '\r')) {
eol = true;
break charLoop;
}
}
startChar = nextChar;
nextChar = i;
if (eol) {
String str;
if (s == null) {
str = new String(cb, startChar, i - startChar);
} else {
s.append(cb, startChar, i - startChar);
str = s.toString();
}
nextChar++;
if (c == '\r') {
skipLF = true;
}
if(skipLF=='\r'){
return str + "\r\n";
}else{
return str + "\n";
}
}
if (s == null)
s = new StringBuffer(defaultExpectedLineLength);
s.append(cb, startChar, i - startChar);
}
}
}
КОД ИСТОЧНИКА отредактирован от:
Одним из решений может быть расширение BufferedReader
и переопределить readLine()
метод (как это уже было предложено в других ответах).
Возьмите этот упрощенный пример только как PoC.
class MyReader extends BufferedReader {
int size = 8192;
public MyReader(Reader in) {
super(in);
}
public MyReader(Reader in, int sz) {
super(in, sz);
this.size = sz;
}
@Override
public String readLine() throws IOException {
StringBuilder sb = new StringBuilder(this.size);
for (int read = super.read(); read >= 0 && read != '\n'; read = super.read()) {
sb.append((char) read);
}
// in case you want also to preserve the line feed character
// sb.append('\n');
return sb.toString();
}
}
,
public class MyReaderDemo{
public static void main(String[] args) throws FileNotFoundException, IOException {
String text = "abcd\n"
+ "efgh\r\n"
+ "ijkl\r";
ByteArrayInputStream bis = new ByteArrayInputStream(
text.getBytes(StandardCharsets.ISO_8859_1)
);
// BufferedReader in = new BufferedReader(new InputStreamReader(bis));
BufferedReader in = new MyReader(new InputStreamReader(bis));
System.out.println(Arrays.toString(in.readLine().getBytes()));
System.out.println(Arrays.toString(in.readLine().getBytes()));
System.out.println(Arrays.toString(in.readLine().getBytes()));
}
}
вывод с BufferedReader
[97, 98, 99, 100]
[101, 102, 103, 104]
[105, 106, 107, 108]
вывод с MyReader
[97, 98, 99, 100]
[101, 102, 103, 104, 13]
[105, 106, 107, 108, 13]
Это, вероятно, не составит большого труда продлить BufferedReader
включить \n
или же \r
в ответ от readLine()
, На самом деле, пакет защищен readLine(boolean ignoreLF)
Функция - это все, что вам нужно переопределить:
Читает строку текста. Строка считается завершенной любым из перевода строки ('\n'), разделителя возврата каретки ('\r') в результате или возврата каретки, за которым сразу следует перевод строки.
Параметры:
ignoreLF
Если true, следующий '\ n' будет пропущенВозвращает:
A String
содержащий содержимое строки, не включая символы окончания строки, или ноль, если достигнут конец потокаБроски:
IOException
Если происходит ошибка ввода-выводаСмотрите также:
LineNumberReader.readLine()