I'm trying to familiarize myself with Java IO classes, so I wrote the code below:
public static void main(String[] args)throws IOException {
FileOutputStream fos = new FileOutputStream("fileIO.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
DataOutputStream dos = new DataOutputStream(bos);
//fos.write(9999);
//bos.write(9999);
dos.writeInt(9999);
dos.writeBytes("中文字(Chinese)\n");
dos.writeChars("中文字(Chinese)\n");
dos.flush();
FileInputStream fis = new FileInputStream("fileIO.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis);
System.out.println(dis.readInt());
System.out.println(dis.readUTF());
}
Unfortunately, I get this:
9999
Exception in thread "main" java.io.EOFException
at java.io.DataInputStream.readFully(DataInputStream.java:180)
at java.io.DataInputStream.readUTF(DataInputStream.java:592)
at java.io.DataInputStream.readUTF(DataInputStream.java:547)
at IO.main(IO.java:34)
Could anyone point out why? Thanks.
Instead of
dos.writeBytes("中文字(Chinese)\n");
dos.writeChars("中文字(Chinese)\n");
you need
dos.writeUTF("中文字(Chinese)\n");
When you perform a readUTF, the first two byte are used for the length. This means if you have random bytes there (not from writeUTF) you will attempt to read very long string instead and as there is not enough data, you will get EOFException.
You can only use readUTF() to read items that were written with writeUTF().
This is true in general for readXXX() and writeXXX() for any XXX (unless you want to read the bytes of an int or some such and you know what you're doing).
I think this link will be helpful. The exception is thrown (from oracle docs) -
if this input stream reaches the end before reading all the bytes.
You haven't UTF char after Integer number in your file. When you're trying read UTF there is End of File so you have the exception.
Try in debug mode stop before you read and check manually to your file, what do you have then?
Related
FileInputStream fin = new FileInputStream(path);
BufferedInputStream bin = new BufferedInputStream(fin);
byte[] inputByte1= new byte[500];
byte[] inputByte2= new byte[500];
byte[] inputByte3 =new byte[34];
bin.read(inputByte1);
bin.read(inputByte2);
bin.read(inputByte3);
Let's say the file had only 400 bytes. How can I detect it?
I know that I could check if (bin.read(inputByte1)!=500)
But this looks really ugly to write in each line.
My main questions is:
How to detect if before filling some array the buffer was done.
I do not want to do bin.read() for each byte and check bin.read!=-1.
First, on a Windows based system you need to escape the \ when you use it as a path separator. Next, you could use a FileInputStream (which you could wrap with a BufferedInputStream). Finally, you should close the InputStream when you're done (or you risk leaking file handles, sockets or some other resource). You might use a try-with-resources statement. Putting it all together, it might look something like
File f = new File("c:\\test\\test.txt");
try (InputStream is = new BufferedInputStream(new FileInputStream(f))) {
int val;
while ((val = is.read()) != -1) {
System.out.println((byte) val);
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
I would recommend a DataInputStream over a BufferedInputStream over a FileInputStream. That way you can use the readFully() method to read exactly as many bytes as you need each time without having to loop.
c:\test\test.txt
Use forward slashes in Java:
c:/test/test.txt
i need to bring out inputstream from inputstream , for example inputstream A is 1024 byte and i need to bring out inputstream B from A of Hundred and fiftieth byte to end , from certain offset to certain end . i search in google and stackoverflow ...Is there any solution available in java ??
You can use the method "skip" to skip the first 150 bytes.
Here is an example:
byte[] buf = {1,2,3,4,5,6,7,8,9};
InputStream is1 = new ByteArrayInputStream(buf);
long skip = is1.skip(5);
System.out.println(is1.read());
If you know that you have a FileInputStream, you can use FileChannel.position() to set where in the file that stream will read from.
FileInputStream in = new FileInputStream("whatever");
FileChannel channel = in.getChannel();
channel.position(10);
This will not work with other types of streams.
I need help on my homework, any help will be much appreciated. I can send small files without a problem. But when i try to send let’s say a 1GB file byte array sends OutOfMemoryError so i need a better solution to send file from server to client. How can i improve this code and send big files, please help me.
Server Code:
FileInputStream fis = new FileInputStream(file);
byte[] fileByte = new byte[fis.available()]; //This causes the problem.
bytesRead = fis.read(fileByte);
oos = new ObjectOutputStream(sock.getOutputStream());
oos.writeObject(fileByte);
Client Code:
ois = new ObjectInputStream(sock.getInputStream());
byte[] file = (byte[]) ois.readObject();
fos = new FileOutputStream(file);
fos.write(file);
Don't read the whole file into memory, use a small buffer and write while you are reading the file:
BufferedOutputStream bos = new BufferedOutputStream(sock.getOutputStream())
File file = new File("asd");
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
byte[] buffer = new byte[1024*1024*10];
int n = -1;
while((n = bis.read(buffer))!=-1) {
bos.write(buffer,0,n):
}
Use Buffered* to optimize the writing and reading from Streams
Just split the array to smaller chunks so that you don't need to allocate any big array.
For example you could split the array into 16Kb chunks, eg new byte[16384] and send them one by one. On the receiving side you would have to wait until a chunk can be fully read and then store them somewhere and start with next chunk.
But if you are not able to allocate a whole array of the size you need on server side you won't be able to store all the data that you are going to receive anyway.
You could also compress the data before sending it to save bandwidth (and time), take a look at ZipOutputStream and ZipInputStream.
Here's how I solved it:
Client Code:
bis=new BufferedInputStream(sock.getInputStream());
fos = new FileOutputStream(file);
int n;
byte[] buffer = new byte[8192];
while ((n = bis.read(buffer)) > 0){
fos.write(buffer, 0, n);}
Server Code:
bos= new BufferedOutputStream(sock.getOutputStream());
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
int n=-1;
byte[] buffer = new byte[8192];
while((n = bis.read(buffer))>-1)
bos.write(buffer,0,n);
Depending on whether or not you have to write the code yourself, there are existing libraries which solve this problem, e.g. rmiio. If you are not using RMI, just plain java serialization, you can use the DirectRemoteInputStream, which is kind of like a Serializable InputStream. (this library also has support for things like auto-magically compressing the data).
Actually, if you are only sending file data, you would be better off ditching the Object streams and use DataInput/DataOutput streams. first write an integer indicating the file length, then copy the bytes directly to the stream. on the receiving side, read the integer file length, then read exactly that many bytes.
when you copy the data between streams, use a small, fixed size byte[] to move chunks of data between the input and output streams in a loop. there are numerous examples of how to do this correctly available online (e.g. #ErikFWinter's answer).
I am trying to receive a file that client sends using DataInputStream and write it into file.
(Client sends the file using DataInputStream write(byte[], len, off) method)
Here's how I am trying to do, but it does not receive full data.
InputStream in = s.getInputStream(); //s is Socket that is connected.
BufferedInputStream bis = new BufferedInputStream(in);
DataInputStream din = new DataInputStream(bis);
FileOutputStream fos = new FileOutputStream(directory+"/"+filename);
byte b = din.readByte();
while(b != -1){
fos.write(b);
b = din.readByte();
}
I know that the implementation above may not be elegant.
but I am really new to java so please forbear with me about bad style
(I really appreciate if you recommend better one if you know)
the result file is only 4KB whereas it should be 401KB
How should I fix this code so I can have my code working?
THank you very much.
you are reading a byte, and -1 (cast to a byte) is a valid byte value. you don't want to stop on -1, but should instead catch EOFException.
you test for -1 when using one of the standard InputStream.read() methods (which return int, not byte).
I get a java.lang.ArrayIndexOutOfBoundsException when using ByteArrayInputStream.
First, I use a ZipInputStream to read through a zip file,
and while looping through the zipEntries,
I use a ByteArrayInputStream to capture the data of each zipEntry
using the
ZipInputStream.read(byte[] b) and ByteArrayInputStream(byte[] b) methods.
At the end, I have a total of 6 different ByteArrayInputStream objects containing data from 6 different zipEntries.
I then use OpenCSV to read through each of the ByteArrayInputStream.
I have no problem reading 4 of the 6 ByteArrayInputStream objects, of which have byte sizes of less than 2000.
The other 2 ByteArrayInputStream objects have byte sizes of 2155 and 4010 respectively and the CSVreader was only able to read part of these 2 objects, then give an java.lang.ArrayIndexOutOfBoundsException.
This is the code I used to loop through the ZipInputStream
InputStream fileStream = attachment.getInputStream();
try {
ZipInputStream zippy = new ZipInputStream(fileStream);
ZipEntry entry = zippy.getNextEntry();
ByteArrayInputStream courseData = null;
while (entry!= null) {
String name = entry.getName();
long size = entry.getSize();
if (name.equals("course.csv")) {
courseData = copyInputStream(zippy, (int)size);
}
//similar IF statements for 5 other ByteArrayInputStream objects
entry = zippy.getNextEntry();
}
CourseDataManager.load(courseData);
}catch(Exception e){
e.printStackTrace();
}
The following is the code with which I use to copy the data from the ZipInputStream to the ByteArrayInputStream.
public ByteArrayInputStream copyInputStream(InputStream in, int size)
throws IOException {
byte[] buffer = new byte[size];
in.read(buffer);
ByteArrayInputStream b = new ByteArrayInputStream(buffer);
return b;
}
The 2 sets of openCSV codes are able to read a few lines of data, before throwing that exception, which leads me to believe that it is the byteArray that is causing the problem. Is there anything I can do or work around this problem?
I am trying to make an application that accepts a zip file, while not storing any temporary files in the web app, as I am deploying to both google app engine and tomcat server.
Fixed!!! Thanks to stephen C, i realized that read(byte[]) does not read everything so I adjusted the code to make the copyInputStream fully functional.
Since this looks like homework, here's a hint:
The read(byte[]) method returns the number bytes read.
On what line do you get the error? And have you checked the value of size? I suspect it's 0