Reading From a File of Numbers Using RandomAccessFile Java - java

I have an assignment to write some numbers in a text file using PrintStream and then reading from that same file using RandomAccessFile. While the writing part works as intended, I get the following output when running my code.
807416096
840971040
874525984
Exception in thread "main" java.io.EOFException
908080928
941635872
at java.io.RandomAccessFile.readInt(RandomAccessFile.java:776)
at Problema4.main(Problema4.java:21)
Java Result: 1
Here is the code:
import java.io.*;
import java.util.*;
public class Problema4 {
public static void main(String[] args) throws IOException, FileNotFoundException
{
PrintStream ps = new PrintStream(new FileOutputStream("fisiernou.txt"));
int i=0;
while (i<11)
{
ps.print(i);
ps.print(" ");
i++;
}
ps.close();
RandomAccessFile raf = new RandomAccessFile("fisiernou.txt", "r");
raf.seek(0);
//System.out.println(raf.readInt());
while (raf.getFilePointer()<raf.length())
System.out.println(raf.readInt());
raf.close();
}
}

You are writing integer as strings ( ps.print(i) ). If you write 1, in the file you are writting the ascii character of 1. Suposse this is the unique number we write, the file then have only one byte.
When reading, you are using raf.readInt(). This method reads 4 bytes and convert them to an integer. If now you try to read your file, this only contains one byte (the ascii character of 1), and then you get an EOF excepcion.
Use the same type of method for writting and reading. You can write with FileOutputStream.write(int).

RandomAccessFile.readInt() reads a binary 32-bit integer from the file. This means that it read 4 bytes and transform those 4 bytes into an int. It doesn't read the string representation of an int. Read its javadoc.

When your raf pointer is reading from the file, it is possible to hit an 'End of File' character. From the Java API:
"It is generally true of all the reading routines in this class that if end-of-file is reached before the desired number of bytes has been read, an EOFException (which is a kind of IOException) is thrown."
http://docs.oracle.com/javase/7/docs/api/java/io/RandomAccessFile.html

Related

what is the variable "data" storing in this java program?

My code is working. I just need to know about the role of a specific variable in the code.
I tried to print the value in the variable "data", but it gives me some numbers i cant understand.
public static void main(String[] args) throws IOException {
FileInputStream fileinputstream = new FileInputStream ("c:\\Users\\USER\\Desktop\\read.TXT");
FileOutputStream fileoutputstream = new FileOutputStream("c:\\Users\\USER\\Desktop\\write.TXT");
while (fileinputstream.available() > 0) {
int data = fileinputstream.read();
fileoutputstream.write(data);
}
fileinputstream.close();
fileoutputstream.close();
}
You can look at the docs for FileInputStream.read, which says:
Reads a byte of data from this input stream. This method blocks if no input is yet available.
Returns:
the next byte of data, or -1 if the end of the file is reached.
So the integer you got (i.e. the number stored in data) is the byte read from the file. Since your file is a text file, it is the ASCII value of the characters in that file (assuming your file is encoded in ASCII).
FileInputStream#read() reads a single byte of information from the underlying file.
Since these files are text files (according to their extensions), you probably should be using a FileInputStream, but a FileReader, to properly handle characters, and not the bytes that make them up.
fileinputstream.read() returns "the next byte of data, or -1 if the end of the file is reached."
You can read more here

Why doesn't Files.newInputStream(path) support the available method on FIFOs?

Take this simple test class:
public class InputStreamTest {
public static void main(String[] args) throws IOException {
byte[] buf = new byte[100];
Path path = Paths.get(args[0]);
System.out.println("File " + path);
try (InputStream is = new BufferedInputStream(new FileInputStream(path.toFile()))) {
// try (InputStream is = new BufferedInputStream(Files.newInputStream(path))) {
System.out.println("Available: " + is.available());
System.out.print("First 100 bytes: '");
is.read(buf);
System.out.write(buf);
System.out.println("'");
}
}
}
This takes a filename/path on the command line and simply prints out the result of available() on the corresponding InputStream and up to1 the first 100 bytes from the stream.
It works fine, even when you pass it redirected command output (which internally will create a FIFO and pass it as the file argument). For example, running it as:
java InputStreamTest <(echo -n "ABC")
... results in the following output:
File /dev/fd/63:
Available: 3
First 100 bytes: 'ABC'
Looks good so far. Now, uncomment the line that uses the new-and-recommended-Java-7-ish Files.newInputStream(path) to create the InputStream and comment our the prior line which uses the oldschool FileInputStream class. Now it fails:
File /dev/fd/63
Exception in thread "main" java.io.IOException: Illegal seek
at sun.nio.ch.FileChannelImpl.position0(Native Method)
at sun.nio.ch.FileChannelImpl.position(FileChannelImpl.java:264)
at sun.nio.ch.ChannelInputStream.available(ChannelInputStream.java:116)
at java.io.BufferedInputStream.available(BufferedInputStream.java:410)
at net.tdowns.compression.InputStreamTest.main(InputStreamTest.java:20)
Evidently the available() method on the stream is failing. Now you might just say "hey, don't call available() it is pretty much useless". Unfortunately, a class as core as BufferedInputStream uses it! If you comment out the direct call to available(), this still fails:
File /dev/fd/63
First 100 bytes: 'Exception in thread "main" java.io.IOException: Illegal seek
at sun.nio.ch.FileChannelImpl.position0(Native Method)
at sun.nio.ch.FileChannelImpl.position(FileChannelImpl.java:264)
at sun.nio.ch.ChannelInputStream.available(ChannelInputStream.java:116)
at java.io.BufferedInputStream.read(BufferedInputStream.java:353)
at java.io.FilterInputStream.read(FilterInputStream.java:107)
at net.tdowns.compression.InputStreamTest.main(InputStreamTest.java:22)
So you are in a pretty tough spot - if you use Files.newInputStream(path), the available() call might fail, and you can't really avoid use of this call since other JDK stream classes themselves like to call it.
Any way out?
1 I say up to because of course the read() method may return fewer than the requested number of bytes, even if more are available. In practice, it doesn't do that for files and for fifos you get at least a few K, so this will usually print out 100 bytes if 100 bytes are available.

how to write UTF8 data to xml file using RandomAccessFile?

When trying to write some UTF8 data to a file, I end up with some garbage in the file. The code is as follows
public static boolean saveToFile(StringBuffer buffer,
String fileName,
ArrayList exceptionList,
String className)
{
log.debug("In saveToFile for file [" + fileName + "]");
RandomAccessFile raf = null;
File file = new File(fileName);
File backupFile = new File(fileName+"_bck");
try
{
if (file.exists())
{
if (backupFile.exists())
{
backupFile.delete();
}
file.renameTo(backupFile);
}
raf = new RandomAccessFile(file, "rw");
raf.writeBytes(buffer.toString());
raf.close();
The output of buffer.toString() is
<?xml version="1.0" encoding="UTF-8"?>
<ivr>
<version>1.1</version>
<templateName>αβγδεζη
The data in the file however is
<?xml version="1.0" encoding="UTF-8"?>
<ivr>
<version>1.1</version>
<templateName>▒▒▒▒▒▒▒</templateName>
How can I make sure that data i nthe file itself is UTF8
I'm not surpised you get garbage:
raf.writeBytes(buffer.toString())
The documentation for RandomAccessFile.writeBytes(String) says (emphasis added):
Writes the string to the file as a sequence of bytes. Each character in the string is written out, in sequence, by discarding its high eight bits.
In a few circumstances, that operation will result in a correctly encoded file. But in most it won't. That writeBytes() method is a foolish design by the Java developers. You need to correctly encode your text as bytes in UTF-8, and then write those bytes.
Do you really need to operate on the file as a random access file. If not, just manipulate it with a Writer wrapping an OutputStream.
You could use Charset.encode(CharBuffer) to produce a ByteBuffer holding the encoded bytes, then write those bytes to the file:
raf.write(StandardCharsets.UTF_8.encode(buffer).array());
The Javadoc for RandomAccessFile states that for writeBytes()
Writes the string to the file as a sequence of bytes. Each character
in the string is written out, in sequence, by discarding its high
eight bits. The write starts at the current position of the file
pointer.
Assuming that discarding parts of your String isn't what you want, you should be using writeUtf():
Writes a string to the file using modified UTF-8 encoding in a
machine-independent manner.
String txt = buffer.toString();
raf.write(txt.getBytes(StandardCharsets.UTF_8));

Java OutputStreamWriter UTF-16 CVS wrong character on StartLine

i need to write a simple CSV file using OutputStreamWriter everything works OK but i have a problem a have in the first Header on the CSV the outer left on every line seems to ADD improperly a Character or a sequence of them in the String here is my Java Code
private final Character SEPARATOR=';';
private final Character LINE_FEED='\n';
public void createCSV(final String fileName)//......
{
try
(final OutputStream outputStream = new FileOutputStream(fileName);
final OutputStreamWriter writer=new OutputStreamWriter(outputStream,StandardCharsets.UTF_16);)
{
final StringBuilder builder = new StringBuilder().append("Fecha").append(SEPARATOR)
.append("NºExp").append(SEPARATOR)
.append("NºFactura").append(SEPARATOR).append(LINE_FEED);
writer.append(builder.toString());
writer.append(builder.toString());
writer.flush();
}catch (IOException e){e.printStackTrace();}
}
unfortunalety i am receiving this ouput always happens in the first line if i repeat the same output to the second line in the CSV everything works smoothly is a Java problem or is my Excel gives me nightmares??.. thank a lot..
OUTPUT
This is a superfluous byte order mark (BOM), \uFFFE, a zero width space, its byte encoding used to determine whether it is UTF-16LE (little endian) or UTF-16-BE (big endian).
Write "UTF16-LE", which has the Windows/Intel ordering of least significant byte, most significant byte.
StandardCharsets.UTF_16LE

Java Binary type in file

I have a problem with binary type. I have binary file with data. Every element is split by "_". I am using
DataInputStream in = new DataInputStream(new FileInputStream("C:/Data/"+names)); , where names is the name of my binary file. How I can read this file and saving elements in array? This is possible?
When writing to a binary file, there is no need to split each items in the matrix with '_'. The program knows how many bytes allocated for each item.
The following code write 2 doubles without '_' in between. After that, it reads them back from the file and output the data.
public class Test {
public static void main(String[] args) throws Exception {
DataOutputStream dos = new DataOutputStream(new FileOutputStream("a.bin"));
dos.writeDouble(1.2);
dos.writeDouble(3.4);
dos.close();
DataInputStream dis = new DataInputStream(new FileInputStream("a.bin"));
System.out.println(dis.readDouble());
System.out.println(dis.readDouble());
dis.close();
}
}
The program outputs:
1.2
3.4
But if you didn't write the file and there is '_' between items, you can use readChar() after reading each item from the binary file as #Bhaskar already mentioned.
Finally, using ObjectOutputStream can write the whole array at once.
public class Test {
public static void main(String[] args) throws Exception {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("a.bin"));
double[] a = {1.2, 3.4};
oos.writeObject(a);
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("a.bin"));
double[] b = (double[]) ois.readObject();
System.out.println(b[0]);
System.out.println(b[1]);
ois.close();
}
}
It depends on how the data was written down into that file. If it was written using DataOutputStream's writeXXX() where XXX stands for the actual data type of elements, and where elements were separated by a writeChar('_') , then you can easily read them back using DataInputStream's readXXX() method. Just make sure that you read the elements in the exact sequence that they were written , and also that you use readChar() whenever you expect the - to be present ( ie between two elements).
You can use read(byte[]) or read(byte[],ffset,length) to read the content of file into byte array.

Categories