I have a project (in Eclipse, but that doesn't matter) with a hierarchy as follows:
-src
---Start.java
---resources
-----media
-------intro.wav
-----textures
-------logo.png
-------tiles.abotm
In Start.java, I'm trying to get tiles.abotm as an InputStream using Class.getResourceAsStream(String) as such:
public class Start
{
public static void main(String[] args)
{
try
{
InputStream in = Start.class.getResourceAsStream(
"/resources/textures/tiles.abotm");
}catch(Exception e){
e.printStackTrace();
}
}
}
Simple enough, right? Unfortunately, no. The InputStream is completely empty with a size of 0. I've also tried opening a FileInputStream directly to the absolute location of tiles.abotm, but I get the same thing! I know the file is not empty. In fact, it has 2,257 bytes, according to Windows, Eclipse, and the File object used to create the FileInputStream mentioned previously. Also according to the File object, it is readable, writable, it exists, it is not a directory, and the name of it is tiles.abotm. So, if the File object can read it, why can't it be opened up in an InputStream??
--EDIT--
I forgot to mention that I have another file in the textures directory called logo.png which I am able to open and read in the exact same manner with no problem at all. It is only this file.
--In reply to fge, this is the actual code:
Loader.loadTextureMap("/resources/textures/tiles.abotm");//This is called in a separate method in a separate class.
public class Loader{
public static TextureMap loadTextureMap(String texMap){
DataInputStream dis = new DataInputStream(
Start.class.getResourceAsStream(texMap));
//It then goes on to read it, but I've determined that at this point,
there is nothing in this DataInputStream.
}
}
After a lot of discussion, the code that works for the OP:
final byte[] buf = new byte[1024]; // or other
final URL url = Start.class.getResource("whatever");
// check for url == null
InputStream in;
ByteArrayOutputStream out;
// I really wish this syntax was something else, it sucks
try (
in = url.openStream();
out = new ByteArrayOutputStream();
) {
int count;
while ((count = in.read(buf)) != -1)
out.write(buf, 0, count);
out.flush();
} catch (IOException e) {
// handle e here
}
final ByteBuffer buffer = ByteBuffer.wrap(out.toByteArray());
// use the buffer
Related
I recently tried to create a copy/paste app with Java using this answer and I didn't change much other than directories of the file. I created a regular text file with "test" written inside it. When I run the app it copies the file, but gives me an error about utf-8 encoding in success_test.txt and I'm not sure how to fix this or what's causing the problem. I'm running this on Ubuntu 18.04 in Intellij Ultimate 2019.2
here's the server and the client is pretty much the same as in the answer
Server:
public class Server extends Thread {
public static final int PORT = 3332;
public static final int BUFFER_SIZE = 626;
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(PORT);
while (true) {
Socket s = serverSocket.accept();
saveFile(s);
}
} catch (Exception e) {
}
}
private void saveFile(Socket socket) throws Exception {
InputStream inputStream = socket.getInputStream();
FileOutputStream fileOutputStream = new FileOutputStream("/home/user/Documents/success_test.txt");;
byte[] byteArray = new byte[1024];
System.out.println("Reading file from server...");
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
int bytesRead;
while ((bytesRead = inputStream.read(byteArray)) != -1) {
bufferedOutputStream.write(byteArray);
}
bufferedOutputStream.close();
System.out.println("Writing file complete...");
}
public static void main(String[] args) {
new Server().start();
}
}
when I try to open success_test.txt this is what I see
https://imgur.com/a/3rpvkiJ
You are reading your data into a 1024 byte long array, then writing that to a file. This means your output file is padded to 1024 bytes with \00 which is the NULL character.
You have your bytesRead variable, so you should use it to only write that many bytes:
bufferedOutputStream.write(byteArray, 0, bytesRead);
As others have mentioned, you have a logic error: you’re ignoring bytesRead in your loop. However, you can eliminate that error, and the possibility of most other errors, by using Files.copy instead of writing your own save code:
try (InputStream inputStream = socket.getInputStream()) {
Files.copy(inputStream,
Paths.get("/home/user/Documents/success_test.txt"));
}
I am writing a small program to retrieve a large number of XML files. The program sort of works, but no matter which solution from stackoverflow I use, every XML file I save locally misses the end of the file. By "the end of the file" I mean approximately 5-10 lines of xml code. The files are of different length (~500-2500 lines) and the total length doesn't seem to have an effect on the size of the missing bit. Currently the code looks like this:
package plos;
import static org.apache.commons.io.FileUtils.copyURLToFile;
import java.io.File;
public class PlosXMLfetcher {
public PlosXMLfetcher(URL u,File f) {
try {
org.apache.commons.io.FileUtils.copyURLToFile(u, f);
} catch (IOException ex) {
Logger.getLogger(PlosXMLfetcher.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
I have tried using BufferedInputStream and ReadableByteChannel as well. I have tried running it in threads, I have tried using read and readLine. Every solution gives me an incomplete XML file as return.
In some of my tests (I can't remember which, sorry), I got a socket connection reset error - but the above code executes without error messages.
I have manually downloaded some of the XML files as well, to check if they are actually complete on the remote server - which they are.
I'm guessing that somewhere along the way a BufferedWriter or BufferedOutputStream has not had flush() called on it.
Why not write your own copy function to rule out FileUtils.copyURLToFile(u, f)
public void copyURLToFile(u, f) {
InputStream in = u.openStream();
try {
FileOutputStream out = new FileOutputStream(f);
try {
byte[] buffer = new byte[1024];
int count;
while ((count = in.read(buffer) > 0) {
out.write(buffer, 0, count);
}
out.flush();
} finally {
out.close();
}
} finally {
in.close();
}
}
I'm trying to running an external program from a Java program and I'm having trouble. Basically what I'd like to do would be this:
Runtime.getRuntime().exec("./extprogram <fileIn >fileOut");
However I've found that that doesn't work - Java apparentls needs to use a Process with input and output streams and other things which I'm not experienced with.
I've looked at a number of examples across the internet (many of which are from SO), and there doesn't seem to be a simple standard way of doing this, which for someone who doesn't fully understand what's going on, can be quite frustrating.
I'm also having trouble trying to build my own code off the examples of other people's code because generally it seems most other people 1. aren't interested in redirecting stdin, and 2. aren't necessarily redirecting stdout to a file, but instead to System.out.
So, would anyone be able to point me in the direction of any good simple code templates for calling external programs and redirecting stdin and stdout? Thanks.
You could try something like this:
ProcessBuilder pb = new ProcessBuilder();
pb.redirectInput(new FileInputStream(new File(infile));
pb.redirectOutput(new FileOutputStream(new File(outfile));
pb.command(cmd);
pb.start().waitFor();
If you must use Process, then something like this should work:
public static void pipeStream(InputStream input, OutputStream output)
throws IOException
{
byte buffer[] = new byte[1024];
int numRead = 0;
do
{
numRead = input.read(buffer);
output.write(buffer, 0, numRead);
} while (input.available() > 0);
output.flush();
}
public static void main(String[] argv)
{
FileInputStream fileIn = null;
FileOutputStream fileOut = null;
OutputStream procIn = null;
InputStream procOut = null;
try
{
fileIn = new FileInputStream("test.txt");
fileOut = new FileOutputStream("testOut.txt");
Process process = Runtime.getRuntime().exec ("/bin/cat");
procIn = process.getOutputStream();
procOut = process.getInputStream();
pipeStream(fileIn, procIn);
pipeStream(procOut, fileOut);
}
catch (IOException ioe)
{
System.out.println(ioe);
}
}
Note:
Be sure to close the streams
Change this to use buffered streams, I think the raw Input/OutputStreams implementation may copy a byte at a time.
The handling of the process will probably change depending on your specific process: cat is the simplest example with piped I/O.
have you tried System.setIn and System.setOut? has been around since JDK 1.0.
public class MyClass
{
System.setIn( new FileInputStream( "fileIn.txt" ) );
int oneByte = (char) System.in.read();
...
System.setOut( new FileOutputStream( "fileOut.txt" ) );
...
I want to include a static log file within my app. Whenever the user starts the app, a time with extra information will be appended to that file. At the beginning, I thought storing the file into assets folder or raw folder would be the solution, but then I looked into android documentations where it states:
Tip: If you want to save a static file in your application at compile
time, save the file in your project res/raw/ directory. You can open
it with openRawResource(), passing the R.raw. resource ID.
This method returns an InputStream that you can use to read the file
(but you cannot write to the original file).
How can I solve this problem?
EDIT:
I want the log file not to be removed on closing the app.
Instead of including the log file with the app you should create it on first launch.
There's more information How to create a file in Android? on creating a file.
Well i don't see the problem, your user will open the app and it will be runtime and you can write what ever you want to what ever file. So this tip doesn't apply to you.
Here is the solution:
private void writeLog(String s)
{
String FILENAME = "log.txt";
FileOutputStream fos = null;
try
{
fos = openFileOutput(FILENAME, Context.MODE_APPEND);
fos.write(s.getBytes());
}
catch(FileNotFoundException e){}
catch(IOException e){}
finally
{
try
{
fos.close();
}
catch(IOException e){}
}
}
private void readLog(EditText logs)
{
String FILENAME = "log.txt";
FileInputStream in = null;
try
{
in = openFileInput(FILENAME);
}
catch(IOException e1){}
try
{
byte[] buffer = new byte[4096]; // Read 4K characters at a time.
int len;
logs.setText("");
while((len = in.read(buffer)) != -1)
{
String s = new String(buffer, 0, len);
logs.append(s);
}
}
catch(IOException e){}
finally
{
try
{
if(in != null) in.close();
}
catch(IOException e){}
}
}
I have a problem to resolve.
I have tar.gz compressed file, and I wouldLike keep the contents like a stream, like Zipfile permits with the method zipFile.getInputStream(zipEntry). I have Implemented using ant library, the code:
TarInputStream is = new TarInputStream(gzipInputStream);
while((entryx = is.getNextEntry()) != null) {
if (entryx.isDirectory()) continue;
else {
InputStream tmpIn = new StreamingTarEntry(is, entryx.getSize());
BufferedReader gzipReader = null;
// simple loop to dump the contents to the console
try {
gzipReader = new BufferedReader(
new InputStreamReader(
new GZIPInputStream(
tmpIn)));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (gzipReader !=null){
buffer.add(gzipReader);
}
}// end of while
is.close();
After I put the BUFFERreader into my linkedList and then retrieve it in the main and wants to print the content of the buffer, i have the exception:
java.io.EOFException: Unexpected end of ZLIB input stream
at java.util.zip.InflaterInputStream.fill(Unknown Source)
Who can Help me???
From what I remember - in a tar.gz the compression is done last - I am not familiar with the class TarInputStream, but I imagine it would work something like
InputStream in = new FileInputStream("myFile");
GZIPInputStream gzipIn = new GZIPInputStream(in);
TarInputStream tarIn= new TarInputStream(gzipIn );
while((entryx = is.getNextEntry()) != null) {
if (entryx.isDirectory()) continue;
else {
InputStream dataIn = new StreamingTarEntry(is, entryx.getSize());
//Process your data here - it is already uncompressed
}
}
ie : A tar.gzip is a tar archive that has been gzipped
It's possible that this is due to a very long-standing bug - see here
I believe you've implemented StreamingTarEntry yourself, as there are no other references in Google and it is not part of the Ant API. From your other question, I think you followed this blog post. Lacking the source to StreamingTarEntry this answer is partially a guess.
The TarInputStream in Ant only allows you to read data out of the current tar entry. You cannot save a reference to a position within the tar file and return to it, but must instead process each file as you reach it. Your StreamingTarEntry class must copy all the data from the current entry into a temporary location in memory or on disk before it calls getNextEntry() or close() on the TarInputStream.