I am trying to understand few java file concepts. So I tried with below program to understand FileOutputStream
FileOutputStream out = new FileOutputStream("test.txt");
int i = 1;
out.write(i);
out.flush();
out.close();
Some binary data has been writen in the file.
But the for the same program when I change the value of i from 1 to 10. I don't see anything in my output file. Can someone explain me why with some internal details.
int i = 1;
out.write(i);
That writes 0x1 to the file.
out.flush();
out.close();
The flush() is redundant.
Some binary data has been writen in the file.
Correct.
But the for the same program when I change the value of i from 1 to 10. I don't see anything in my output file.
Yes you do. You see 0xa, which is a line feed character.
Related
I have a problem transferring a file over socket.
I Wrote a simple client / server app and the client takes a screenshot and send it to server.
The problem is the file is not completed whatever i do, It's always missing the first byte from the array which makes the photo damaged.
When I open the photo in any hex editor and compare the original photo with the one that the client sent, I can see the missing byte, as if I add it, the photo opens without the problem. The size of the sent file missing just one byte !
Here is a photo for the problem :
Original photo
sent photo
Here is the code :
Server ( Receiver ) :
byte[] buf;
InputStream inp;
try (BufferedOutputStream out1 = new BufferedOutputStream(new FileOutputStream(new File("final.jpeg")))) {
buf = new byte[s.getReceiveBufferSize()];
inp = new DataInputStream(s.getInputStream());
Thread.sleep(200);
int len = 0;
while ((len = inp.read(buf)) >0){
out1.write(buf,0,len);
}
out1.flush();
inp.close();
out1.close();
}
Client ( Sender ):
BufferedImage screenshot = new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(screenshot, "jpeg", os);
ImageIO.write(screenshot, "jpeg", new File("test.jpeg"));
OutputStream out = new BufferedOutputStream( connection.getOutputStream());
out.write(os.toByteArray());
out.close();
I have tried to send the array with the same way I receive it but no lock. I have tried with, and without buffered, I have tried flush in both sides, I tried to turn off Nod antivirus, Tried a sleep when sending length,
I almost tried everything without success .
I have tried on both, My pc and a virtual machine windows 7 !
Any help will be appreciated.
Edit :
First 10 bytes from the original file :
first 10 bytes from the sent file :
The code you posted does not lose data. Somewhere prior to executing the server code you posted, you have executed a single InputStream.read() of one byte, possibly in a misguided attempt to test for end of stream.
The sleep is just literally a waste of time. Remove it. You don't need the DataInput/OutputStreams either.
Please keep in mind that DataInputStream signals end of stream by returning value -1 from read() therefore your server reading loop should look like this:
while ((len = inp.read(buf)) != -1){
out1.write(buf,0,len);
}
Perhaps this helps.
The client code looks fine. Must be the server. You only posted the part when "some" input stream is written to a file. What happens before? Anyone doing a read() on the input stream?
Sorry for writing this in the "answer" section. Apparently, I cannot comment yet.
Ok it was my fault ! I was looking for something wrong in server side but the fault was in client side ! I opened a DataInputStream to read the order coming from server without closing it and that was the problem.
I was trying to read from file and then write to other file. I use code bellow to do so.
byte[] bytes = Files.readAllBytes(file1);
Writer Writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file2), "UTF-8"));
for(int i=0;i<bytes.length;i++)
Writer.write(bytes[i]);
Writer.close();
But when I change file1 to picture.png and file2 to picture2.png, this method doesn't work and I can't open picture2.png using image viewer.
What have I done wrong?
Writers are for writing text, possibly in different formats (ie utf-8 / 16, etc). For writing raw bytes, don't use writers. Just use (File)OutputStreams.
It is truly as simple as
byte[] bytes = ...;
FileOutputStream fos = ...;
fos.write(bytes);
The other answers explain why what you have potentially fails.
I'm curious why you're already using one Java NIO method, but not others? The library already has methods to do this for you.
byte[] bytes = Files.readAllBytes(file1);
Files.write(file2, bytes, StandardOpenOption.CREATE_NEW); // or relevant OpenOptions
or
FileOutputStream out = new FileOutputStream(file2); // or buffered
Files.copy(file1, out);
out.close();
or
Files.copy(file1, file2, options);
The problem is that Writer.write() doesn't take a byte. It takes a char, which is variable size, and often bigger than one byte.
But once you've got the whole thing read in as a byte[], you can just use Files.write() to send the whole array to a file in much the same way that you read it in:
Files.write(filename, bytes);
This is the more modern NIO idiom, rather than using an OutputStream.
It's worth reading the tutorial.
I am implementing a Direct Connect client. I am using the NMDC protocol. I can connect to a hub and other connected clients. I am trying to retrieve the file list from each client, I understand that in order to do that one must download the file files.xml.bz2 from the other client. The protocol to download a file is as follows:
-> $ADCGET file <filename> <params>|
<- $ADCSND file <fileName> <params>|
<- (*** binary data is now transfered from client B to client A ***)
I am trying to create a file named files.xml.bz2 using the binary data received. Here's my code:
//filesize is provided through the $ADCSND response from other client
byte[] data = new byte[filesize];
/*
Reading binary data from socket inputstream
*/
int read = 0;
for (int i=0; read<filesize;){
int available = in2.available();
int leftspace = filesize-read;
if (available>0){
in2.read(data, read, available>leftspace? leftspace:available);
++i;
}
read += (available>leftspace? leftspace:available)+1;
}
/*
writing the bytes to an actual file
*/
ByteArrayInputStream f = new ByteArrayInputStream(data);
FileOutputStream file = new FileOutputStream("files.xml.bz2");
file.write(data);
file.close();
The file is created, however, the contents (files.xml) are not readable. Opening it in firefox gives:
XML Parsing Error: not well-formed
Viewing the contents in the terminal only reads binary data. What am i doing wrong?
EDIT
I also tried Decompressing the file using the bz2 libray from Apache Ant.
ByteArrayInputStream f = new ByteArrayInputStream(data);
BZip2CompressorInputStream bzstream = new BZip2CompressorInputStream(f);
FileOutputStream xmlFile = new FileOutputStream("files.xml");
byte[] bytes = new byte[1024];
while((bzstream.read(bytes))!=-1){
xmlFile.write(bytes);
}
xmlFile.close();
bzstream.close();
I get an error, here's the stacktrace:
java.io.IOException: Stream is not in the BZip2 format
at org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream.init(BZip2CompressorInputStream.java:240)
at org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream.<init>(BZip2CompressorInputStream.java:132)
at org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream.<init>(BZip2CompressorInputStream.java:109)
at control.Controller$1.run(Controller.java:196)
Usual, typical misuse of available(). All you need to copy a stream in Java is as follows:
while ((count = in.read(buffer)) >= 0)
{
out.write(buffer, 0, count);
}
Use this with any size buffer greater than zero, but preferably several kilobytes. You don't need a new buffer per iteration, and you don't need to know how much data is available to read without blocking, as you have to block, otherwise you're just smoking the CPU. But you do need to know how much data was actually read per iteration, and this is the first place where your code falls down.
The error java.io.IOException: Stream is not in the BZip2 format is generated by the constructor of class BZip2CompressorInputStream. I decided to scan the bytes, looking for the magic number to make sure that the file was bz2 format, it turns out that Java was right -- it wasnt in bz2 format.
Upon examining the source code of Jucy, I saw that the reason for this was a slight error in the command I sent to the other client, in essence, this error was caused a mistake in my protocol implementation. The solution was:
Replace:
$ADCGET file files.xml.bz2 0 -1 ZL1|
With:
$ADCGET file files.xml.bz2 0 -1|
ZL1 specifies compression of the files being sent (Not necessary).
I'm trying to output a byte array to a file. The String that I create displays correctly when I call System.out.println(ouput_stream). Hover, it does not output correctly when I use a FileOutputStream. Here's what I've got so far. Any suggestions?
FileOutputStream fos = new FileOutputStream("outputFile.txt");
OutputStreamWriter out = new OutputStreamWriter(fos, "UTF-8");
String received_string = new String(rPacket.getData(), 0, rPacket.getLength(), "UTF-8");
System.out.println(received_string);
out.write(received_string, 0, received_string.length());
The console displays the information the information when I call the System.out.println(received_string. However, it doesn't output the file correctly. I asked a similar question earlier, but now am struggling on the output. Thanks for any help.
Have a look at Apache Commons FileUtils.writeByteArrayToFile
Should do what you need
Your code looks a bit weird (do you want bytes or Strings), but should be okay.
What did you find in the file? Did you close the stream/writer before looking at it? If not, it is likely still being buffered somewhere.
Try to avoid the conversion to String, though, if you really want to just pipe that packet to a file.
Don't use a String or a Writer at all. Just copy the bytes directly from the packet to the file:
fos.write(rPacket.getData(), rPacket.getOffset(), rPacket.getLength());
Then you can't possibly corrupt the data.
Try using BufferedWriter ..
BufferedWriter writer = new BufferedWriter(new FileWriter("outfile"));
writer.write(received_string);
I have used the code in this stackoverflow discussion in order to calculate the checksum of a file in java.
I am a little confused about this working I am applying this in my problem as follows :
I have a file with some data. I have calculated the size of the text in the file using
System.out.println(file1content.toString().getBytes().length); the o/p is 4096 bytes
When i try to execute the checksum code I realize that the number of bytes being read is 4096+12 bytes, is this 12 bytes equal to the filename ?
I have another file2 with the same content as file1 ( i know this for sure because I extract the text to a String and compare it with String.equals) but the checksum generated is different. I am wondering why this is happening ?
Am I missing something here ?
Edit 1:
I am reading data from the file using the following loop :
InputStream fis = new FileInputStream(filename);
byte[] buffer = new byte[1024];
do {
numRead = fis.read(buffer);
System.out.println(" "+ numRead);
if (numRead > 0) {
complete.update(buffer, 0, numRead);
}
} while (numRead != -1);
fis.close();
The output of numread is :
1024
1024
1024
1024
12
-1
Regards,
Bhavya
Well I found out what the bug was, I am not sure if this I introduced the bug or if it was already there.
I realised that the data being read from the file was not correct, some portions of the file were read multiple times, so I modified the code so that I could obtain data from the file by specifying the start and end positions.
In case anyone is facing this issue please let me know I can post the solution for this.
Regards,