How to read multiple lines using only FileReader?

I have the following code:

public class Reader { public static void main(String[] args) throws IOException { try (FileReader in = new FileReader("D:/test.txt")) { // BufferedReader br = new BufferedReader(in); int line = in .read(); for (int i = 0; i < line; i++) { //System.out.println(line); System.out.println((char) line); line = in .read(); } } } } 

and the file Test.txt with the contents:

 Hello Java 

When I run the code above, it reads only Hello . I would like to read a few lines using only FileReader . I do not want to use BufferedReader or InputStreamReader , etc. Is it possible?

0
java filereader
source share
6 answers

Reading a file character with a character without a buffering stream is extremely inefficient. I would probably wrap FileReader in some BufferedReader or just use Scanner to read the condensed file, but if you absolutely want / need / should use only FileReader, you can try with

 int line = in.read(); while (line != -1) { System.out.print((char) line); line = in.read(); } 

instead of your for (int i = 0; i < line; i++) {...} loop for (int i = 0; i < line; i++) {...} .

Read the slims answer carefully. In short: the reading condition should not worry if the number of characters read is less than the numerical representation of the currently read character ( i < line ). As is the case

 My name is not important now 

There are several characters in this file that you usually won't see as \r and \n , and actually it looks like

 My name\r\n \r\n is\r\n \r\n not important now 

where the numeric representation of \r is 10 , so after you read My name\r\n (these are 9 characters, because \r and \n are single characters representing a line separator), your i will become 10 and after the next character which you try to read will be \r , which is also represented by 10 , your i<line condition will fail ( 10<10 is incorrect).

So, instead of checking i<line you should check if the read value is not EoF (End of File, or End of Stream in out case), which is -1 , as indicated in the read method documentation , so your condition should look like line != -1 . And since you don't need i , just use while here.

Return:

The character is read, or -1 if the end of the stream is reached

+1
source share

I do not think this version of the code prints "Hello".

You call:

 int line = in.read(); 

What does it do? Take a look in Javadocs on Reader :

public int read ()

throws an IOException

Reads one character . This method will block until a character is available, an I / O error occurs, or the end of the stream.

(my accent)

Your code reads "H" from "Hello", which is 72 in ASCII.

Then it goes into your loop with line == 72, so it goes into the loop:

  for(int i=0;i<line;i++) 

... making the decision "is 0 less than 72? Yes, so I will go into the loop cycle."

Then, each time he reads a character, the line value changes to another integer, and each time cycle approaches i . So the loop says: "Continue moving until the ASCII character value is greater than the number of iterations I counted."

... and every time he goes, he prints this character on a separate line.

As it happens, for your input it reads the end of the file (-1), and as -1 < i the loop continuation condition is not fulfilled.

But for longer inputs, it stops at the first "a" after the 97th character or in the first "b" after the 98th character, etc. (since ASCII "a" is 97, etc.)

 H e l l o J a v a 

This is not what you want:

  • You do not want your loop to repeat until I> = "the character I just read." You want it to repeat until in.read() returns -1 . You were probably taught to quote until the condition is met.
  • You do not want println() each character, as this adds new lines that you do not need. Use print() .

You should also look at the Reader.read(byte[] buffer) method Reader.read(byte[] buffer) and see if you can write code to work in large chunks.


Two patterns that you will use over and over in your programming career:

  Type x = getSomehow(); while(someCondition(x)) { doSomethingWith(x); x = getSomehow(); } 

... and ...

  Type x = value_of_x_which_meets_condition; while(someCondition(x)) { x = getSomehow(); doSomethingWith(x); } 

See if you can build something with FileReader and the value that you get from it by filling out somehows.

+3
source share

You will need to read the contents of char on char and parse the new string sequence.

The new string sequence can be any of the following:

  • one caries return '\r'
  • single line channel '\n'
  • carriage return followed by the string "\r\n"

EDIT

You can try the following:

 public List<String> readLinesUsingFileReader(String filename) throws IOException { List<String> lines = null; try (FileReader fileReader = new FileReader(filename)) { lines = readLines(fileReader); } return lines; } private List<String> readLines(FileReader fileReader) throws IOException { List<String> lines = new ArrayList<>(); boolean newLine = false; int c, p = 0; StringBuilder line = new StringBuilder(); while(-1 != (c = fileReader.read())) { if(c == '\n' && p != '\r') { newLine = true; } else if(c == '\r') { newLine = true; } else { if(c != '\n' && c != '\r') { line.append((char) c); } } if(newLine) { lines.add(line.toString()); line = new StringBuilder(); newLine = false; } p = c; } if(line.length() > 0) { lines.add(line.toString()); } return lines; } 

Please note that the above code reads the entire file in a List , this may not be suitable for large files! In this case, you may want to implement an approach that uses streaming, that is, read one line at a time, for example String readNextLine(FileReader fileReader) { ... } .

Some basic tests:

Create test files for reading

 private final static String txt0 = "testnl0.txt"; private final static String txt1 = "testnl1.txt"; private final static String txt2 = "testnl2.txt"; @BeforeClass public static void genTestFile() throws IOException { try (OutputStream os = new FileOutputStream(txt0)) { os0.write(( "Hello\n" + ",\r\n" + "World!" + "").getBytes()); } try (OutputStream os = new FileOutputStream(txt1)) { os.write(( "\n" + "\r\r" + "\r\n" + "").getBytes()); } try (OutputStream os = new FileOutputStream(txt2)) { os.write(( "").getBytes()); } } 

Testing using generated files

 @Test public void readLinesUsingFileReader0() throws IOException { List<String> lines = readLinesUsingFileReader(txt0); Assert.assertEquals(3, lines.size()); Assert.assertEquals("Hello", lines.get(0)); Assert.assertEquals(",", lines.get(1)); Assert.assertEquals("World!", lines.get(2)); } @Test public void readLinesUsingFileReader1() throws IOException { List<String> lines = readLinesUsingFileReader(txt1); Assert.assertEquals(4, lines.size()); Assert.assertEquals("", lines.get(0)); Assert.assertEquals("", lines.get(1)); Assert.assertEquals("", lines.get(2)); Assert.assertEquals("", lines.get(3)); } @Test public void readLinesUsingFileReader2() throws IOException { List<String> lines = readLinesUsingFileReader(txt2); Assert.assertTrue(lines.isEmpty()); } 
+1
source share

If you have a new line character

  public static void main(String[]args) throws IOException{ FileReader in = new FileReader("D:/test.txt"); char [] a = new char[50]; in.read(a); // reads the content to the array for(char c : a) System.out.print(c); //prints the characters one by one in.close(); } 

He will print

 Hello Java 
0
source share

Reader.read () returns the int code of a single char or -1 if the end of the file is reached:

http://docs.oracle.com/javase/7/docs/api/java/io/Reader.html#read ()

So, read the char file on char and check LF (Line feed, '\ n', 0x0A, 10 in decimal), CR (carriage return, '\ r', 0x0D, 13 in decimal) and trailing codes.

Note. Windows uses 2 characters to encode the end of the line: "\ r \ n". Most others, including Linux, MacOS, etc., use only "\ n" to encode the end of the line.

  final StringBuilder line = new StringBuilder(); // line buffer try (FileReader in = new FileReader("D:/test.txt")) { int chAr, prevChar = 0x0A; // chAr - just read char, prevChar - previously read char while (prevChar != -1) { // until the last read char is EOF chAr = in.read(); // read int code of the next char switch (chAr) { case 0x0D: // CR - just break; // skip case -1: // EOF if (prevChar == 0x0A) { break; // no need a new line if EOF goes right after LF // or no any chars were read before (prevChar isn't // changed from its initial 0x0A) } case 0x0A: // or LF System.out.println("line:" + line.toString()); // get string from the line buffer line.setLength(0); // cleanup the line buffer break; default: // if any other char code is read line.append((char) chAr); // append to the line buffer } prevChar = chAr; // remember the current char as previous one for the next iteration } } 
0
source share

I solved the problem above using this code

  public class Reader { public static void main(String[]args) throws IOException{ try (FileReader in = new FileReader("D:/test.txt")) { int line = in.read(); while(line!=-1) { System.out.print((char)line); line = in.read(); } } } } 

But there is one more question if I write for a cycle, and not how it is

 for(int i=0;i<line;i++) 

It prints only the first line. Can someone tell me why?

0
source share

All Articles