Read file path from utf-8 text file? - java

I have a UTF-8 text file example.txt that contains:
c:/temp/file.txt
I read the file content using this method:
public static String fileToString(final File file, final String charset) throws AppServerException
{
final byte[] buffer = new byte[(int) file.length()];
FileInputStream fileInputStream = null;
try
{
fileInputStream = new FileInputStream(file);
fileInputStream.read(buffer);
}
catch (final FileNotFoundException e)
{
throw new AppServerException(e.getMessage());
}
catch (final IOException e)
{
throw new AppServerException(e.getMessage());
}
finally
{
FileHelper.close(fileInputStream);
}
try
{
return new String(buffer,charset);
}
catch (UnsupportedEncodingException e)
{
throw new AppServerException(e.getMessage());
}
}
Then I want to check if the file c:/temp/file.txt exists:
String content = fileToString("example.txt","UTF8");
File file = new File(content );
System.out.println(file.exists());
The exits() return false but the file actually exists.
If I change the encoding of example.txt to ANSI using notepad++, the exists() return true.
I already tried using:
"c:\temp\file.txt",
"c:\\temp\\file.txt",
"c:\\\\temp\\\\file.txt",
but without success.
I really need to use the file as UTF8. Do you have tips so the method exists() returns true?

Notepad++ probably puts a Byte Order Mark in front of the file. This is unnecessary for UTF-8 and Java does not interpret this sequence of three characters.
Either use an editor that does not use a Byte Order Mark or write the string in ANSI if your filename does not contain any non-ASCII characters.

Perhaps the file is not actually encoded as UTF-8. Can you print the actual byte values of the "\" characters in the file?
While you are at it: InputStream.read(byte[] b) is not guaranteed to read b.length bytes from the stream. You should be reading in a loop and checking the return value of the read() method in order to see how many bytes were actually read in each call.

Related

How to detect file type from its content in zip archive?

I have a zip archive that contains several gzip files. But gzip file's extentions are also .zip . I walk through zip archive with ZipInputStream. How can I detect inner file's type with reading its content rather than extentions. I also need not to change (or reset) ZipInputStream position.
So I need;
Read files in zip with using inputStream (ZipInputStream in my case) Because zip in zip is possible.
Find file type from its content.
While finding file type from its content, inputStream position should not change. Because i will continue to read next files.
Example:
root/1.zip/2.zip/3.zip(actually 3 is gzip)/4.txt
Sample Java Code:
public static void main(String[] args) {
//root/1.zip/2.zip/3.zip(actually 3 is gzip)/4.txt
String file = "root/1.zip";
File rootZip = new File(file);
try (FileInputStream fis = new FileInputStream(rootZip)) {
lookupInZip(fis)
.stream()
.forEach(System.out::println);
} catch (IOException e) {
System.out.println("Failed to get files");
}
}
public static List<String> lookupInZip(InputStream inputStream) throws IOException {
Tika tika = new Tika();
List<String> paths = new ArrayList<>();
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
ZipEntry entry = zipInputStream.getNextEntry();
while (entry != null) {
String entryName = entry.getName();
if (!entry.isDirectory()) {
//Option 1
//String fileType = tika.detect(entryName);
//Option 2
String fileType = tika.detect(zipInputStream);
if ("application/zip".equals(fileType)) {
List<String> innerPaths = lookupInZip(zipInputStream);
paths.addAll(innerPaths);
} else {
paths.add(entryName);
}
}
entry = zipInputStream.getNextEntry();
}
return paths;
}
If I use option 1, '3.zip' is evaluated as zip file but it is gzip.
If I use option 2, '2.zip' is evaluated as zip correctly by using its content. But when lookupInZip() is called for '3.zip' recursively, zipInputStream.getNextEntry() returns null. Because in previous step, we use inputStream content to detect type and inputStrem position changed.
Note: tika.detect() uses BufferedInputStream in implementation to reset inputStream position but it does not solve my problem.
The first two bytes are enough to see if it is likely a zip file, likely a gzip file, or certainly something else.
If the first two bytes are 0x50 0x4b, then it is likely a zip file. If the first two bytes are 0x1f 0x8b, then it is likely a gzip file. If it is neither, then the file is something else.
The first two bytes matching is not a guarantee it is that type, but it appears from your structure that it is usually one or the other, and you can use the extension as further corroborating evidence that it is compressed.
As for not changing the position, you need a way to peek at the first two bytes without advancing the position, or a way to get them and then unget them to return the position to where it was.

Unable to append to file based on file.length() operation

I want to append to the file and if its not empty; and want to write if its empty. Below is is my code. write function works, append is not. Can anyone guide here?
public class Filecreate {
public static void main(String args[]) throws IOException {
File file = new File("newFileCreated.txt");
System.out.println("file path "+file.getAbsolutePath() +" file length - "+file.length());
FileWriter myWriter = new FileWriter(file);
if((int)file.length() != 0){
myWriter.append("appended text\n");
}else{
myWriter.write("Files in Java might be tricky, but it is fun enough!");
}
myWriter.close();
System.out.println("file length after writing to file "+file.length());
}
}
You don't need to worry about whether or not the file contains anything. Just apply the argument of true to the append parameter in the FileWriter constructor then always use the Writer#append() method, for example:
String ls = System.lineSeparator();
String file = "MyFile.txt";
FileWriter myWriter = new FileWriter(file, true)
myWriter.append("appended text" + ls);
/* Immediately write the stream to file. Only really
required if the writes are in a loop of some kind
and you want to see the write results right away.
The close() method also flushes the stream to file
before the close takes place. */
myWriter.flush();
System.out.println("File length after writing to file " +
new File(file).length());
myWriter .close();
If the file doesn't already exist it will be automatically created
and the line appended to it.
If the file is created but is empty then the line is appended to it.
If the file does contain content then the line is merely appended to
that content.
The issue occurs because you measure file's size after you open it. Thus, you have to check file's size before you open it. Also, I won't recommend to cast long to int, because your solution won't work on big files. To conclude, following code will work for you:
public static void main(String[] args) throws IOException {
File file = new File("newFileCreated.txt");
long fileSize = file.length();
System.out.println("file path "+file.getAbsolutePath() +" file length - "+file.length());
FileWriter myWriter = new FileWriter(file);
if(fileSize > 0L){
myWriter.append("appended text\n");
}else{
myWriter.write("Files in Java might be tricky, but it is fun enough!");
}
myWriter.close();
System.out.println("file length after writing to file "+file.length());
}

How can i write to a .txt file stored on an online server in Java?

Heyy. I want to use java to write specific Strings to a .txt file which I hosted on my domain on awardspace. On awardspace, I edited the permissions so reading and writing is allowed. But for now I only figured out how to read from the file, and it works. Is there a way I can write to it?
You can use a simple method to append to a file. Just pass in the path of the file and the data to write to the file.
I normally use UTF-8 to ensure any special characters come out correctly.
public static void appendToFileUtf8(String file, String data) {
try {
FileOutputStream fout = new FileOutputStream(file, true);
OutputStreamWriter outwrite = new OutputStreamWriter(fout, "UTF-8");
outwrite.write(data);
outwrite.close();
} catch (IOException e) {
throw new RuntimeException("Error writing to file: "+file+" "+e.getMessage());
}
}

Unable to create temporary file in Java

I have a Java method that takes byte array and String value as arguments and returns a File object. This is the code
public File createTempFile(byte[] byteArray, String fileName) throws IOException {
String prefix = FilenameUtils.getBaseName(fileName);
String suffix = getMimeType(byteArray);
File tempFile = File.createTempFile(prefix, suffix, null);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(tempFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
fos.write(byteArray);
fos.close();
return tempFile;
}
When I try to run it like this
File myFile = tiedostoService.createTempFile(tiedosto.getContent(), attachment.getFileName());
I get an IOException like this
java.io.IOException: Unable to create temporary file, C:\Users\ROSHAN~1\AppData\Local\Temp\kuva1068864619970584773image\png
at java.io.File$TempDirectory.generateFile(File.java:1921)
at java.io.File.createTempFile(File.java:2010)
From the stacktrace. it can be seen that it's trying to create a file like C:\Users\ROSHAN~1\AppData\Local\Temp\kuva1068864619970584773image\png
and not C:\Users\ROSHAN~1\AppData\Local\Temp\kuva1068864619970584773image.png
How can I fix this? I'd really appreciate any sort of help.
'image/png' is a Mime Type. See all MimeTypes in java here
Write a util which converts mimetype to file extension. Hopefully this will help.
I think there is an extra \ in your suffix string, could you try debug and see the actual value of the suffix?
I tried to run:
String suffix = "\\png";
and got the same error, but if I do
String suffix = ".png";
no error creating the temp file, notice that you need to add a dot in the suffix...

How to remove null character from file content in java

I receive an XML file from a client. I've another file containing Base-64 encoded data which I embed in one of the elements in XML file. After doing all this merging, I need to return the content of file either as string or a DOM object, returning as InputStream will not work.
But the resulting merged file has null character at the end which is causing issues when file is processed as XML. How can I get rid of it. This is how I am merging my files.
public Object merge(List<File> files) throws Exception {
System.out.println("merge with arguments is called");
if(files == null || files.isEmpty() || files.size()<2){
throw new IllegalArgumentException("File list cannot be null/empty and minimum 2 files are expected");
}
File imageFile = getImageFile(files);
File indexFile = getIndexFile(files);
File inProcessFile = new File("temp/" + indexFile.getName().replaceFirst("[.][^.]+$", "") + ".xml");
File base64EncodedFile = toBase64(imageFile);
/* Write from index file everything till attachment data to inProcess file*/
Scanner scanner = new Scanner(indexFile).useDelimiter("\\s*<AttachmentData>\\s*");
FileWriter writer = new FileWriter(inProcessFile);
writer.append(scanner.next());
/* Write <AttachmentData> element into inProcess file */
writer.append("<AttachmentData>");
/* Write base64 encoded image data into inProcess file */
IOUtils.copy(new FileInputStream(base64EncodedFile), writer);
/* Write all data from </AttachmentData> element from index file into inProcess file */
String fileAsString = IOUtils.toString(new BufferedInputStream(new FileInputStream(indexFile)));
String afterAttachmentData = fileAsString.substring(fileAsString.indexOf("</AttachmentData>"));
InputStream input = IOUtils.toInputStream(afterAttachmentData);
IOUtils.copy(input, writer);
/* Flush the file, processing completed */
writer.flush();
writer.close();
System.out.println("Process completed");
}
private File getIndexFile(List<File> files) {
for(File file:files){
String extension = FilenameUtils.getExtension(file.getName());
if(extension.equalsIgnoreCase(IDX_FILE_EXT))
return file;
}
throw new IllegalArgumentException("Index file doesn't exist or cannot be read.");
}
private File getImageFile(List<File> files) {
for(File file:files){
String extension = FilenameUtils.getExtension(file.getName());
if(extension.equalsIgnoreCase(IMG_FILE_EXT))
return file;
}
throw new IllegalArgumentException("Image file doesn't exist or cannot be read.");
}
private File toBase64(File imageFile) throws Exception {
System.out.println("toBase64 is called");
Base64InputStream in = new Base64InputStream(new FileInputStream(imageFile), true);
File f = new File("/temp/" + imageFile.getName().replaceFirst("[.][^.]+$", "") + ".txt");
Writer out = new FileWriter(f);
IOUtils.copy(in, out);
return f;
}
Please help me understand how I can fix my code which produces null character
Fix the code that produces it, perhaps by removing part or the whole of it. To find this out, you should ask yourself the following questions:
Is the null character already present in the original XML file received from the client?
In what position of the XML document does the element that contains the base-64 data appear?
In what position of the XML document does the null character appear?
Are you decoding the base-64 file in any form?
Does the base-64 file contain the null character?
If yes, why?
What method is used to "merge" the base-64-encoded data into the XML document?
As per information produced later by the OP, and if the file always contains the null character, the simplest solution is to replace line:
String afterAttachmentData = fileAsString.substring(fileAsString.indexOf("</AttachmentData>"));
with
String afterAttachmentData = fileAsString.substring(fileAsString.indexOf("</AttachmentData>"),fileAsString.length()-1);
However, in the long run it's much better to check with the client if the null character is generated on their end of things and, if so, suggest them to to correct the code that generates it so the XML document is valid.

Categories