0

Here's the code:

Properties prop = new Properties();

FileInputStream fis = new FileInputStream("src/prop.txt");

//Read the content
byte[] bys = new byte[1024];
int len;
while((len=fis.read(bys))!=-1) {
  System.out.println(new String(bys));
}

//Load the properties and print
prop.load(fis);
fis.close();
System.out.println(prop);

The src/prop.txt is simple as:

city=LA
country=USA

It prints out nothing in the prop, meaning the prop is empty:

{}

But if I remove the part of reading, prop can be loaded as:

{country=USA, city=LA}

Why is it failed to fulfill the prop after reading the content of prop.txt?

  • What are you trying to do? – guninvalid May 31 '22 at 05:01
  • I want to load the key-value pairs to prop. But prop is empty if I read the content of the prop.txt. If I don't read them, it's loaded. I wonder why. – chiefVincent May 31 '22 at 05:19
  • You have a typo after `System.out.println(new String(bys))`, there should be a `;` insated of `'` at the end. – Ricky Mo May 31 '22 at 05:23
  • It was a type. I corrected it. – chiefVincent May 31 '22 at 05:26
  • 1
    you have a `*Stream`, that is, a **sequence** of bytes - once you read it, you cannot just re-read it (without jumping back [if possible]) || you could use a `FilterInputStream` and *divert* the bytes into an array while reading the Properties; or use the byte array to create a `ByteArrayInputStream` to read the Properties from. – user16320675 May 31 '22 at 06:45
  • 2
    Just get rid of the loop that prints the `InputStream` to `System.out`. This is the problem, and you don't need it. – user207421 May 31 '22 at 07:00
  • I know the loop is not needed here. But the point is that I'd like to know WHY. – chiefVincent May 31 '22 at 10:10

3 Answers3

1

After you read the stream, the stream pointer points to the end of the stream. After that when prop.load() try to read from the stream, nothing more is available. You have to call reset() on the stream before reading it again.

Properties prop = new Properties(); 
BufferedInputStream fis = new BufferedInputStream(new FileInputStream("src/prop.txt"));

fis.mark(fis.available())  //set marker at the begining


//Read the content
byte[] bys = new byte[1024];
int len;
while((len=fis.read(bys))!=-1) {
  System.out.println(new String(bys));
}

fis.reset(); //reset the stream pointer to the begining

//Load the properties and print
prop.load(fis);
fis.close();
System.out.println(prop);
Ricky Mo
  • 6,285
  • 1
  • 14
  • 30
  • Thx. But it got IOexception: mark/reset not supported – chiefVincent May 31 '22 at 05:39
  • Sorry for missing that out. You can use [BufferedInputStream](https://stackoverflow.com/questions/5496172/is-there-a-way-to-create-fileinputstream-with-mark-feature) instead – Ricky Mo May 31 '22 at 06:36
  • `reset()` does not 'reset the stream pointer to the beginning', and it will do exactly nothing without a prior `mark()` even when supported. Don't post guesswork here. – user207421 May 31 '22 at 06:59
  • added `mark()` in the answer. – Ricky Mo May 31 '22 at 07:03
  • Thanks for the advice. I looked it up once but forget about the usage of mark. But I did remember the document says `the stream is reset to a state such that all the bytes read since the most recent call to mark (or since the start of the file, if mark has not been called)`. May I ask about under what circumstances could it fall into `"since the start of the file, if mark has not been called"`, if this is not the case? – Ricky Mo May 31 '22 at 07:10
  • Well, Ricky's answer got the point, which revealed the stream pointer thing that I didn't know before. The mark/reset thing, honestly, I'm not interested, but good to know anyway (they need to be used together like a pair). Salute to you guys! – chiefVincent May 31 '22 at 10:08
1

It prints out nothing in the prop, meaning the prop is empty:

Because you have already gone through the data available in your input stream fis, by fis.read(bys) in your while condition (see what actually read​(byte[] b) does), and there is nothing left when you're loading it into your properties.

FileInputStream is not a type that holds the data persistently; it's rather an object, that represents a pipe, a connection to the file descriptor, and data flows from the file, byte by byte, as long as you keep calling .read(..) on it.

Also, read Oracle docs:

FileInputStream is meant for reading streams of raw bytes such as image data. For reading streams of characters, consider using FileReader

Giorgi Tsiklauri
  • 9,715
  • 8
  • 45
  • 66
-1

Better use ResourceBundle for loading the properties file. Assuming that you are using maven, you can place the properties file name application.properties in the folder "src/main/resources" and you load and using below code:

    ResourceBundle resourceBundle = ResourceBundle.getBundle("application");
    String value = resourceBundle.getString("key");

Please refer to the javadocs of ResourceBundle for more details.

More examples at https://mkyong.com/java/java-resourcebundle-example/ or https://www.baeldung.com/java-resourcebundle

  • I'd like to know why it failed to load the properties if I read the txt file. It loaded fine without reading the file. I don't see why reading the file can fail the properties loading. – chiefVincent May 31 '22 at 05:30