I am trying to make a file converter that converts any file to a Base64 String that gets saved to a .txt file. To avoid too high memory usage when decoding/encoding I am using a buffer that reads the file in small chunks.
import java.io.*;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.util.Base64;
import java.util.Base64.Encoder;
import java.util.Base64.Decoder;
public class Fileconverter {
static long CHUNK_SIZE = (long) Math.pow(2, 10);
public static void encode(String path){
try {
File inputFile = new File(path);
File outputFile = new File("tmp.txt");
FileInputStream fis = new FileInputStream(inputFile);
FileOutputStream fos = new FileOutputStream(outputFile);
Encoder encoder = Base64.getEncoder().withoutPadding();
long file_len = inputFile.length();
long filesize = inputFile.length();
while(file_len > 0) {
byte[] buf = new byte[(int)Math.min(file_len, CHUNK_SIZE)];
file_len-=fis.read(buf);
fos.write(encoder.encode(buf));
System.out.print("\rProcessing: "+Math.round((((file_len*1.0/filesize*1.0)*100)-100)*(-1))+"% ");
}
fis.close();
fos.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
public static void decode(String pName){
try {
File inputFile = new File("tmp.txt");
File outputFile = new File(pName);
FileInputStream fis = new FileInputStream(inputFile);
FileOutputStream fos = new FileOutputStream(outputFile);
Decoder decoder = Base64.getDecoder();
long file_len = inputFile.length();
long filesize = inputFile.length();
while(file_len > 0) {
byte[] buf = new byte[(int) Math.min(file_len, CHUNK_SIZE)];
file_len-=fis.read(buf);
fos.write(decoder.decode(buf));
System.out.print("\rProcessing: "+Math.round((((file_len*1.0/filesize*1.0)*100)-100)*(-1))+"% ");
}
fis.close();
fos.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
The problem is that as soon as the input file requires multiple buffers to get read, it comes out corrupted and I don't know why.
You don't need to do all that. Java IO will handle all that for you with sane defaults. I haven't been through your code with a fine-toothed comb, but the error will most probably have been introduced with the unnecessary complexity. It has to be said that if you're only comfortable with allocating a buffer of up to 1KiB, then you're probably working in the wrong language - Java isn't known for its memory economy.
public static void encodeToBase64(String inputPath, String outputPath) {
Encoder encoder = Base64.getEncoder().withoutPadding();
try (InputStream in = Files.newInputStream(Path.of(inputPath));
OutputStream out = encoder.wrap(Files.newOutputStream(Path.of(outputPath)))) {
in.transferTo(out);
} catch (IOException e) {
throw new RuntimeException(e);
}
}