Java file encoding conversion from ANSI to UTF8 - java

I have a requirement to change the encoding of a file from ANSI(windows-1252) to UTF8. I wrote below program to do it through java. This program converts the characters to UTF8, but when I opened the file in notepad++ the encoding type was displayed as ANSI as UTF8. This gives me error when I import this file in access db. A file with UTF8 encoding only is desired. Also the requirement is to convert the file without opening it in any editor.
public class ConvertFromAnsiToUtf8 {
private static final char BYTE_ORDER_MARK = '\uFEFF';
private static final String ANSI_CODE = "windows-1252";
private static final String UTF_CODE = "UTF8";
private static final Charset ANSI_CHARSET = Charset.forName(ANSI_CODE);
public static void main(String[] args) {
List<File> fileList;
File inputFolder = new File(args[0]);
if (!inputFolder.isDirectory()) {
return;
}
File parentDir = new File(inputFolder.getParent() + "\\"
+ inputFolder.getName() + "_converted");
if (parentDir.exists()) {
return;
}
if (parentDir.mkdir()) {
} else {
return;
}
fileList = new ArrayList<File>();
for (final File fileEntry : inputFolder.listFiles()) {
fileList.add(fileEntry);
}
InputStream in;
Reader reader = null;
Writer writer = null;
try {
for (File file : fileList) {
in = new FileInputStream(file.getAbsoluteFile());
reader = new InputStreamReader(in, ANSI_CHARSET);
OutputStream out = new FileOutputStream(
parentDir.getAbsoluteFile() + "\\"
+ file.getName());
writer = new OutputStreamWriter(out, UTF_CODE);
writer.write(BYTE_ORDER_MARK);
char[] buffer = new char[10];
int read;
while ((read = reader.read(buffer)) != -1) {
System.out.println(read);
writer.write(buffer, 0, read);
}
}
reader.close();
writer.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Any pointers will be helpful.
Thanks,
Ashish

The posted code correctly transcodes from windows-1252 to UTF-8.
The Notepad++ message is confusing because "ANSI as UTF-8" has no obvious meaning; it appears to be an open defect in Notepad++. I believe Notepad++ means UTF-8 without BOM (see the encoding menu.)
Microsoft Access, being a Windows program, probably expects UTF-8 files to start with a byte-order-mark (BOM).
You can inject a BOM into the document by writing the code point U+FEFF at the start of the file:
import java.io.*;
import java.nio.charset.*;
public class Ansi1252ToUtf8 {
private static final char BYTE_ORDER_MARK = '\uFEFF';
public static void main(String[] args) throws IOException {
Charset windows1252 = Charset.forName("windows-1252");
try (InputStream in = new FileInputStream(args[0]);
Reader reader = new InputStreamReader(in, windows1252);
OutputStream out = new FileOutputStream(args[1]);
Writer writer = new OutputStreamWriter(out, StandardCharsets.UTF_8)) {
writer.write(BYTE_ORDER_MARK);
char[] buffer = new char[1024];
int read;
while ((read = reader.read(buffer)) != -1) {
writer.write(buffer, 0, read);
}
}
}
}

On Windows 7 (64-Bit), running Java 8, I had to close every file. Otherwise, files get truncated to multiples of 4 kB. It is not enough to close the last set of files, I had to close every file to get the desired result. Posting my adapted version that adds error messages:
import java.io.*;
import java.nio.charset.*;
import java.util.ArrayList;
public class ConvertFromAnsiToUtf8 {
private static final char BYTE_ORDER_MARK = '\uFEFF';
private static final String ANSI_CODE = "windows-1252";
private static final String UTF_CODE = "UTF8";
private static final Charset ANSI_CHARSET = Charset.forName(ANSI_CODE);
private static final String PATH_SEP = "\\";
private static final boolean WRITE_BOM = false;
public static void main(String[] args)
{
if (args.length != 2) {
System.out.println("Please name a source and a target directory");
return;
}
File inputFolder = new File(args[0]);
if (!inputFolder.isDirectory()) {
System.out.println("Input folder " + inputFolder + " does not exist");
return;
}
File outputFolder = new File(args[1]);
if (outputFolder.exists()) {
System.out.println("Folder " + outputFolder + " exists - aborting");
return;
}
if (outputFolder.mkdir()) {
System.out.println("Placing converted files in " + outputFolder);
} else {
System.out.println("Output folder " + outputFolder + " exists - aborting");
return;
}
ArrayList<File> fileList = new ArrayList<File>();
for (final File fileEntry : inputFolder.listFiles()) {
fileList.add(fileEntry);
}
InputStream in;
Reader reader = null;
Writer writer = null;
int converted = 0;
try {
for (File file : fileList) {
try {
in = new FileInputStream(file.getAbsoluteFile());
reader = new InputStreamReader(in, ANSI_CHARSET);
OutputStream out = new FileOutputStream(outputFolder.getAbsoluteFile() + PATH_SEP + file.getName());
writer = new OutputStreamWriter(out, UTF_CODE);
if (WRITE_BOM)
writer.write(BYTE_ORDER_MARK);
char[] buffer = new char[1024];
int read;
while ((read = reader.read(buffer)) != -1) {
writer.write(buffer, 0, read);
}
++converted;
} finally {
reader.close();
writer.close();
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(converted + " files converted");
}
}

Related

How to implement Parallel Zip Creation with ScatterZipOutputStream with Zip64 Support?

I am wondering if any one can help implementing Parallel Zip Creation using ScatterZipOutputStream . I have searched a lot but no where I am finding an example for the same.
https://commons.apache.org/proper/commons-compress/zip.html
I have tried making Zip, Zipping a directory etc with ZipArchiveOutputStream . Now, I am trying to do that in parallel.
public static void makeZip(String filename) throws IOException,
ArchiveException {
File sourceFile = new File(filename);
final OutputStream out = new FileOutputStream(filename.substring(0, filename.lastIndexOf('.')) + ".zip");
ZipArchiveOutputStream os = new ZipArchiveOutputStream(out);
os.setUseZip64(Zip64Mode.AsNeeded);
os.putArchiveEntry(new ZipArchiveEntry(sourceFile.getName()));
IOUtils.copy(new FileInputStream(sourceFile), os);
os.closeArchiveEntry();
os.close();
}
It should be able to process individual files as thread and then combine it to write the result zip.
Following is the working code of both zip and unzip:
1. Change path for sourceFolder and zipFilePath
2. Zipping only *.text type of files it can be any type or all the files
3. Unzipped files at sourceFolder/unzip/
Import following dependency in build.gradle or in pom.xml
implementation("org.apache.commons:commons-compress:1.18")
implementation("commons-io:commons-io:2.6")
Ref: https://mvnrepository.com/artifact/org.apache.commons/commons-compress/1.18
https://mvnrepository.com/artifact/commons-io/commons-io/2.6
//code
import org.apache.commons.compress.archivers.zip.*;
import org.apache.commons.compress.parallel.InputStreamSupplier;
import org.apache.commons.io.FileUtils;
import java.io.*;
import java.nio.file.Files;
import java.util.Iterator;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class ZipMain {
static ParallelScatterZipCreator scatterZipCreator = new ParallelScatterZipCreator();
static ScatterZipOutputStream dirs;
static {
try {
dirs = ScatterZipOutputStream.fileBased(File.createTempFile("java-zip-dirs", "tmp"));
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
String sourceFolder = "/Users/<user>/Desktop/";
String zipFilePath = "/Users/<user>/Desktop/Desk.zip";
String fileTypesToBeAddedToZip = "txt";
zip(sourceFolder, zipFilePath, fileTypesToBeAddedToZip);
unzip(zipFilePath, sourceFolder + "/unzip/");
}
private static void zip(String sourceFolder, String zipFilePath, String fileTypesToBeAddedToZip) throws IOException {
OutputStream outputStream = null;
ZipArchiveOutputStream zipArchiveOutputStream = null;
try {
File srcFolder = new File(sourceFolder);
if (srcFolder.isDirectory()) {
// uncomment following code if you want to add all files under srcFolder
//Iterator<File> fileIterator = Arrays.asList(srcFolder.listFiles()).iterator();
Iterator<File> fileIterator = FileUtils.iterateFiles(srcFolder, new String[]{fileTypesToBeAddedToZip}, true);
File zipFile = new File(zipFilePath);
zipFile.delete();
outputStream = new FileOutputStream(zipFile);
zipArchiveOutputStream = new ZipArchiveOutputStream(outputStream);
zipArchiveOutputStream.setUseZip64(Zip64Mode.AsNeeded);
int srcFolderLength = srcFolder.getAbsolutePath().length() + 1; // +1 to remove the last file separator
while (fileIterator.hasNext()) {
File file = fileIterator.next();
// uncomment following code if you want to add all files under srcFolder
//if (file.isDirectory()) {
// continue;
// }
String relativePath = file.getAbsolutePath().substring(srcFolderLength);
InputStreamSupplier streamSupplier = () -> {
InputStream is = null;
try {
is = Files.newInputStream(file.toPath());
} catch (IOException e) {
e.printStackTrace();
}
return is;
};
ZipArchiveEntry zipArchiveEntry = new ZipArchiveEntry(relativePath);
zipArchiveEntry.setMethod(ZipEntry.DEFLATED);
scatterZipCreator.addArchiveEntry(zipArchiveEntry, streamSupplier);
}
scatterZipCreator.writeTo(zipArchiveOutputStream);
}
if (zipArchiveOutputStream != null) {
zipArchiveOutputStream.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (outputStream != null) {
outputStream.close();
}
}
}
private static void unzip(String zipFilePath, String destDir) {
File dir = new File(destDir);
// create output directory if it doesn't exist
if (!dir.exists()) {
dir.mkdirs();
} else {
dir.delete();
}
FileInputStream fis;
//buffer for read and write data to file
byte[] buffer = new byte[1024];
try {
fis = new FileInputStream(zipFilePath);
ZipInputStream zis = new ZipInputStream(fis);
ZipEntry ze = zis.getNextEntry();
while (ze != null) {
String fileName = ze.getName();
File newFile = new File(destDir + File.separator + fileName);
System.out.println("Unzipping to " + newFile.getAbsolutePath());
//create directories for sub directories in zip
String parentFolder = newFile.getParent();
File folder = new File(parentFolder);
folder.mkdirs();
FileOutputStream fos = new FileOutputStream(newFile);
int len;
while ((len = zis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
//close this ZipEntry
zis.closeEntry();
ze = zis.getNextEntry();
}
//close last ZipEntry
zis.closeEntry();
zis.close();
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Ref: Fast zipping folder using java ParallelScatterZipCreator

File Handling used for saving files in a recursive manner

I have my code generating two files with rewritable data. I need a code that continues generating the files with recursive file names and should keep all the previous files as well .
In the below code, every time i have to update my file, I have to hard code it and copy it into a new file.
I want a recursive function that saves the file, named numerically in an order(Ascending), while keeping the data in my previous file as well, everytime i run the code.
public static void main(String[] args) throws IOException
{
createFileUsingFileClass();
copyFileVersion();
fileChecker();
String data_2 = "This is the new data written in your file";
writeUsingFileWriter(data_2);
copyFileInCode(data_2);
}
private static void createFileUsingFileClass() throws IOException
{
File file = new File("C:\\Users\\esunrsa\\Documents\\file.txt");
//Create the file
if (file.createNewFile()){
System.out.println("File is created!");
}else{
System.out.println("File already exists.");
}
//Write Content
FileWriter writer = new FileWriter(file);
String data_1 = " Initial data";
writer.write(data_1);
writer.close();
}
private static void copyFileVersion() {
FileInputStream ins = null;
FileOutputStream outs = null;
try {
File infile =new File("C:\\Users\\esunrsa\\Documents\\file.txt");
File outfile =new File("C:\\Users\\esunrsa\\Documents\\file_01.txt");
ins = new FileInputStream(infile);
outs = new FileOutputStream(outfile);
byte[] buffer = new byte[1024];
int length;
while ((length = ins.read(buffer)) > 0) {
outs.write(buffer, 0, length);
}
ins.close();
outs.close();
System.out.println("File created successfully!!");
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
private static void fileChecker() {
File f = new File("C:\\Users\\esunrsa\\Documents\\sunrita.txt");
if(f.exists()){
System.out.println("File existed");
}else{
System.out.println("File doesnt exist");
System.exit(0);
//System.out.println("File not found!");
}
}
private static void writeUsingFileWriter(String data_2) {
File file = new File("C:\\Users\\esunrsa\\Documents\\file.txt");
FileWriter fr = null;
try {
fr = new FileWriter(file);
fr.write(data_2);
} catch (IOException e) {
e.printStackTrace();
}finally{
//close resources
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static void copyFileInCode(String filename) {
FileInputStream ins = null;
FileOutputStream outs = null;
try {
File infile =new File("C:\\Users\\esunrsa\\Documents\\file.txt");
File outfile =new File("C:\\Users\\esunrsa\\Documents\\file_02.txt");
ins = new FileInputStream(infile);
outs = new FileOutputStream(outfile);
byte[] buffer = new byte[1024];
int length;
while ((length = ins.read(buffer)) > 0) {
outs.write(buffer, 0, length);
}
ins.close();
outs.close();
System.out.println("File created successfully!!");
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
}

How can I make this faster at reading and writing?

public class DataMiner {
private static BigData app = new BigData();
private static DomainOfConstants doc = new DomainOfConstants();
private static Logger log = Logger.getLogger(DataMiner.class);
private static DBManager conn = new DBManager();
private static java.sql.Connection con = null;
private static AmazonS3 s3Client;
private static Iterator<String> itr;
private static List<String> entries = new ArrayList<String>();
private static S3Object s3Object;
private static ObjectMetadata meta;
public static InputStream dataStream;
public static byte[] buffer = new byte[1024];
public static File file = new File(app.getCurrentPacsId()+".txt");
private static void obtainConnection(){
conn.connection();
entries = conn.grabDataSet();
conn.closeDb();
downloadBucket();
}
/*
*
* The Java heap size limits for Windows are:
* maximum possible heap size on 32-bit Java: 1.8 GB
* recommended heap size limit on 32-bit Java: 1.5 GB (or 1.8 GB with /3GB option)
*
* */
/*-------------Download and un-zip backup file-------------*/
private static void downloadBucket(){
try {
app.setAwsCredentials(doc.getAccessKey(), doc.getSecretKey());
s3Client = AmazonS3ClientBuilder.standard().withCredentials(new AWSStaticCredentialsProvider(app.getAwsCredentials())).withRegion(Regions.US_EAST_1).build();
System.out.println("Connected to S3");
itr = entries.iterator();
while(itr.hasNext()){
app.setBucketKey(itr.next());
String key = app.getBucketKey();
app.setCurrentPacsId(key);
s3Object = s3Client.getObject(new GetObjectRequest(doc.getDesiredBucket(), app.getBucketKey()));
try {
ZipInputStream zis = new ZipInputStream(s3Object.getObjectContent());
ZipEntry entry = zis.getNextEntry();
extractObjects(buffer, s3Client, zis, entry);
} catch (AmazonServiceException e) {
log.error(e);
} catch (SdkClientException e) {
log.error(e);
} catch (IOException e) {
log.error(e);
}
}
System.out.println("Processing complete");
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
public static void extractObjects(byte[] buffer, AmazonS3 s3Client, ZipInputStream zis, ZipEntry entry) throws IOException {
PipedOutputStream outputStream = null;
PipedInputStream is = null;
try {
while (entry != null)
{
String fileName = entry.getName();
if (fileName == "lib") {
fileName = entry.getName();
}
boolean containsBackup = fileName.contains(doc.getDesiredFile());
if (containsBackup == true) {
System.out.println("A back up file was found");
long start = System.currentTimeMillis();
formatSchemaName();
System.out.println("Extracting :" + app.getCurrentPacsId());
log.info("Extracting " + app.getCurrentPacsId() + ",
compressed: " + entry.getCompressedSize() + " bytes,
extracted: " +
entry.getSize() + " bytes");
//ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
outputStream = new PipedOutputStream();
is = new PipedInputStream(outputStream);
int len;
while ((len = zis.read(buffer)) >= 0)
{
outputStream.write(buffer, 0, len);
}
//InputStream is = new ByteArrayInputStream(outputStream.toByteArray());
meta = new ObjectMetadata();
meta.setContentLength(file.length());
fileName = app.getCurrentPacsId();
runDataConversion(is,s3Client,fileName);
recordTime(start);
is.close();
outputStream.close();
System.out.println("Unzip complete");
}
else{
System.out.println("No back up found");
}
entry = zis.getNextEntry();
}
zis.closeEntry();
zis.close();
} catch (AmazonServiceException e) {
log.error(e);
} catch (SdkClientException e) {
log.error(e);
}
}
/*------------Formating the replacment file name---------*/
private static void formatSchemaName(){
String s3Key = app.getCurrentPacsId();
String id = s3Key.replace(".zip", ".txt");
id = id.substring(id.indexOf("_"));
id = id.replaceFirst("_", "");
app.setCurrentPacsId(id);
}
/*---------------Process the data file----------------------*/
private static void runDataConversion(PipedInputStream is, AmazonS3 s3Client, String fileName) {
DataProcessor convert = new DataProcessor(s3Client);
convert.downloadBucket(is,fileName);
}
/*-------Records execution time of program in min/sec------*/
private static void recordTime(long start) throws IOException {
long end = System.currentTimeMillis();
long minutes = TimeUnit.MILLISECONDS.toMinutes(end - start);
long seconds = TimeUnit.MILLISECONDS.toSeconds(end - start);
System.out.println("Execution speed "+ minutes + ":" + (seconds % 60) +" min/sec\n");
}
And here is the class that does some text file processing.The code is very slow overall when processing files up to 3.5gb. It takes 3 hours to do so while running. I have tried using piped streams over byte streams. Java heap size set to -xms2800m on a 64 bit JDK.
public class DataProcessor {
private static AmazonS3 s3Client;
private static ObjectMetadata meta;
private static DomainOfConstants doc = new DomainOfConstants();
private static BigData app = new BigData();
public static File file = new File(app.getCurrentPacsId()+".txt");
private static Logger log = Logger.getLogger(DataProcessor.class);
//Construct connection
public DataProcessor (AmazonS3 s3Client){
this.s3Client = s3Client;
}
//
public void downloadBucket(PipedInputStream is, String fileName) {
try {
File dataStream = dataConversion(is);
s3Client.putObject(doc.getDestinationBucket(),FilenameUtils.getFullPath(doc.getDestinationKey()) + "Modified_"+ fileName, dataStream);
} catch (AmazonServiceException e) {
e.printStackTrace();
log.error(e);
} catch (SdkClientException e) {
e.printStackTrace();
log.error(e);
}
}
//Setup reading and writing streams
public static File dataConversion(PipedInputStream stream) {
BufferedReader reader = null;
BufferedOutputStream streamOut = null;
String line;
try {
reader = new BufferedReader(new InputStreamReader(stream,doc.getFileFormat()));
streamOut = new BufferedOutputStream(new FileOutputStream(file));
meta = new ObjectMetadata();
while(( line = reader.readLine() ) != null)
{
processLine(reader, streamOut, line);
}
}
catch (IOException e) {
e.printStackTrace();
} finally {
try {
streamOut.close();
reader.close();
} catch (IOException e) {
e.printStackTrace();
log.error(e);
}
}
return file;
}
/*---------------------------------------Data processing------------------------------------------------*/
/*-----------Process and print lines---------*/
private static void processLine(BufferedReader reader, BufferedOutputStream streamOut, String line) {
try {
String newLine = System.getProperty("line.separator");
while (reader.ready()) {
if (line.contains(doc.getInsert())) {
handleData(streamOut, line);
} else if (line.contains(doc.getUse())) {
handleSchemaName(streamOut, line);
} else {
streamOut.write(line.toLowerCase().getBytes(Charset.forName(doc.getFileFormat()).toString()));
streamOut.write(newLine.getBytes());
}
line = reader.readLine();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
log.error(e);
} catch (IOException e) {
e.printStackTrace();
log.error(e);
}
}
/*-----------Replace-Schema-Name-----------*/
private static void handleSchemaName(BufferedOutputStream streamOut, String line) throws IOException {
line = line.replace(line, "USE " + "`" + doc.getSchemaName() + app.getCurrentPacsId() + "`;");
streamOut.write(line.getBytes(Charset.forName(doc.getFileFormat())));
}
/*--------Avoid-Formating-Data-Portion-of-file--------*/
private static void handleData(BufferedOutputStream streamOut, String line) throws IOException {
StringTokenizer tk = new StringTokenizer(line);
while (tk.hasMoreTokens()) {
String data = tk.nextToken();
if (data.equals(doc.getValue())) {
streamOut.write(data.toLowerCase().getBytes(Charset.forName(doc.getFileFormat()).toString()));
data = tk.nextToken();
while (tk.hasMoreTokens()) {
streamOut.write(data.getBytes(Charset.forName(doc.getFileFormat())));
data = tk.nextToken();
}
}
streamOut.write(line.toLowerCase().getBytes(Charset.forName(doc.getFileFormat().toString())));
streamOut.write(" ".getBytes(Charset.forName(doc.getFileFormat())));
}
}
Rule 1 is always to use a bigger buffer. 1024 is pitifully small. Try 32-64K.
You need to start the pipe reading thread before doing any writes to the pipe. In fact I'm surprised you don't get 'read end dead' errors. Does this code really work at all?
In fact get rid of the piped streams. Use a single thread and do all the processing as you go.
Get rid of the ready() test. It is an extra system call for nothing. Just read until end of stream.
Use a BufferedWriter instead of a BufferedOutputStream and stop converting all those strings to bytes (and use BufferedWriter.newLine() instead of the system property).

Why server-side shows a null pointer exception (in client server application)?

In my client server application, client sends some commands and the server gives the results back. Now the problem is when the client tries to download a file from the server, by using GET filename command. The program works fine, even it can doesnload the file correctly, but the problem is in the server side's command prompt there is always a null pointer exception error remains. And it happens immediately after I enter the GET command. Error:
Second issue appears when I remove fis.close(); line in serverside. It shows another trace error in the server side: Error:
This is the complete project I am working on:
ClientSide:
package clientside;
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class ClientSide {
private static Socket socket;
private static PrintWriter outputToServer;
private static BufferedReader inputFromServer;
private static InputStream is;
private static FileOutputStream fos;
private static final int PORT = 8000;
private static final String SERVER = "85.197.159.45";
boolean Connected;
DataInputStream serverInput;
public static void main(String[] args) throws InterruptedException {
String server = "localhost";
int port = PORT;
if (args.length >= 1) {
server = args[0];
}
if (args.length >= 2) {
port = Integer.parseInt(args[1]);
}
new ClientSide(server, port);
}
public ClientSide(String server, int port) {
try {
socket = new Socket(server, port);
serverInput = new DataInputStream(socket.getInputStream());
outputToServer = new PrintWriter(socket.getOutputStream(), true);
inputFromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("Client is connected! ");
Connected = true;
String line = null;
Scanner sc = new Scanner(System.in);
System.out.print("Type command: ");
while (sc.hasNextLine()) {
String request = sc.nextLine();
if (request.startsWith("exit")) {
outputToServer.println(request);
System.out.println("Application exited!");
//outputToServer.flush();
break;
} else if (request.startsWith("pwd")) {
outputToServer.println(request);
outputToServer.flush();
} else if (request.startsWith("list")) {
outputToServer.println(request);
outputToServer.flush();
} else if (request.startsWith("GET")) {
System.out.print("\r\n");
outputToServer.println(request);
outputToServer.flush();
}
while (Connected) {
line = inputFromServer.readLine();
System.out.println(line);
if (line.isEmpty()) {
Connected = false;
if (inputFromServer.ready()) {
System.out.println(inputFromServer.readLine());
}
}
if (line.startsWith("Status 400")) {
while (!(line = inputFromServer.readLine()).isEmpty()) {
System.out.println(line);
}
break;
}
if (request.startsWith("GET")) {
File file = new File(request.substring(4));
is = socket.getInputStream();
fos = new FileOutputStream(file);
byte[] buffer = new byte[socket.getReceiveBufferSize()];
serverInput = new DataInputStream(socket.getInputStream());
//int bytesReceived = 0;
byte[] inputByte = new byte[4000];
int length;
while ((length = serverInput.read(inputByte, 0, inputByte.length)) > 0) {
fos.write(inputByte, 0, length);
}
/*
while ((bytesReceived = is.read(buffer)) >=0) {
//while ((bytesReceived = is.read(buffer))>=buffer) {
fos.write(buffer, 0, bytesReceived);
}
*/
request = "";
fos.close();
is.close();
}
}
System.out.print("\nType command: ");
Connected = true;
}
outputToServer.close();
inputFromServer.close();
socket.close();
} catch (IOException e) {
System.err.println(e);
}
}
}
ServerSide:
package serverside;
import java.io.*;
import java.net.*;
import java.util.Arrays;
public class ServerSide {
private BufferedReader inputFromClient;
private PrintWriter outputToClient;
private FileInputStream fis;
private OutputStream os;
private static final int PORT = 8000;
private ServerSocket serverSocket;
private Socket socket;
public static void main(String[] args) {
int port = PORT;
if (args.length == 1) {
port = Integer.parseInt(args[0]);
}
new ServerSide(port);
}
private boolean fileExists(File[] files, String filename) {
boolean exists = false;
for (File file : files) {
if (filename.equals(file.getName())) {
exists = true;
}
}
return exists;
}
public ServerSide(int port) {
// create a server socket
try {
serverSocket = new ServerSocket(port);
} catch (IOException ex) {
System.out.println("Error in server socket creation.");
System.exit(1);
}
while (true) {
try {
socket = serverSocket.accept();
os = socket.getOutputStream();
outputToClient = new PrintWriter(socket.getOutputStream());
inputFromClient = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (true) {
String request = inputFromClient.readLine();
if (!request.startsWith("exit") && !request.startsWith("pwd") && !request.startsWith("list") && !request.startsWith("GET")) {
outputToClient.println("Wrong request\r\n"
+ "\r\n");
} else if (request.startsWith("exit")) {
break;
} else if (request.startsWith("pwd")) {
File file = new File(System.getProperty("user.dir"));
outputToClient.print("Status OK\r\n"
+ "Lines 1\r\n"
+ "\r\n"
+ "Working dir: " + file.getName() + "\r\n");
} else if (request.startsWith("list")) {
File file = new File(System.getProperty("user.dir"));
File[] files = file.listFiles();
outputToClient.print("Status OK\r\n"
+ "Files " + files.length + "\r\n"
+ "\r\n"
+ Arrays.toString(files).substring(1, Arrays.toString(files).length() - 1) + "\r\n");
} else if (request.startsWith("GET")) {
String filename = request.substring(4);
File file = new File(System.getProperty("user.dir"));
File[] files = file.listFiles();
if (fileExists(files, filename)) {
file = new File(filename);
int fileSize = (int) file.length();
outputToClient.printf("Status OK\r\nSize %d Bytes\r\n\r\nFile %s Download was successfully\r\n",
fileSize, filename);
outputToClient.flush();
try (FileInputStream fis = new FileInputStream(file)) {
byte[] buffer = new byte[(1 << 7) - 1];
int bytesRead = 0;
while ((bytesRead = fis.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
}
os.close();
fis.close();//NPE is happening here.
} else {
outputToClient.print("Status 400\r\n"
+ "File " + filename + " not found\r\n"
+ "\r\n");
outputToClient.flush();
}
}
outputToClient.flush();
}
} catch (IOException e) {
System.err.println(e);
}
finally{
os.close();
}
}
}
}
UPDATE: Even if I remove the fis.close(); line from the server side, it shows java.net.SocketException: socket closed error.
The original problem is that you are using a try-with-resources block with an assigned variable with the same name as one of your class member variables. Removing the following line will remove the NPE:
fis.close();
The SocketException is being caused by the line:
os.close();
According to the documentation of Socket::getOutputStream:
Closing the returned OutputStream will close the associated socket.
Therefore, moving the line os = socket.getOutputStream(); to just below the line socket = serverSocket.accept(); line, and also moving os.close() to a finally block after your final catch block should solve this issue.
The socket represented by fis is null.
To correct, use this:
if (fis != null) fis.close;
try (FileInputStream fis = new FileInputStream(file))
In this line you are creating a new FileInputStream and using it, and it is not your FileInputStream field, declared before. This fis exists only on the "try" block. When you try to close your fis os.close(); you are trying to close your fis field, not the fis declared in the try.
Use this, instead:
try (fis = new FileInputStream(file)). With this you are instantiating a new FileInputStream in your field, not in a new variable.

DeflaterOutputStream won't output valid file

I'm using DeflaterOutputStream in combination with Buffered input and output streams, trying to just compress a simple file which I should be able to decompress with the second program (it also adds a number at the end of a line but this is irrelevant). However, it's not creating a valid compressed file. When I try to decompress it, it just creates a blank file. I think it might have something to do with flushing. Any thoughts?
public class Program {
static String inputFileName = "inputfile.txt";
static String outputFileName = "outputfile.txt";
public static void main(String[] args) {
try {
FileInputStream fileInputStream = new FileInputStream(inputFileName);
BufferedInputStream inputBuff = new BufferedInputStream(fileInputStream);
FileOutputStream fileOutputStream = new FileOutputStream(outputFileName);
BufferedOutputStream outputBuff = new BufferedOutputStream(fileOutputStream);
DeflaterOutputStream deflater = new DeflaterOutputStream(outputBuff);
int fileByte;
while ((fileByte =inputBuff.read()) != -1)
{
deflater.write(fileByte);
}
deflater.flush();
outputBuff.flush();
fileOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class Program2 {
static String inputFileName = "outputfile.txt";
static String outputFileName = "decoutputfile.txt";
public static void main(String[] args) {
try {
FileInputStream fileInputStream = new FileInputStream(inputFileName);
BufferedInputStream inputBuff = new BufferedInputStream(fileInputStream);
FileOutputStream fileOutputStream = new FileOutputStream(outputFileName);
BufferedOutputStream outputBuff = new BufferedOutputStream(fileOutputStream);
InflaterOutputStream inflater = new InflaterOutputStream(outputBuff);
int fileByte;
int lineCount = 1;
while ((fileByte =inputBuff.read()) != -1)
{
if (fileByte == '\n'){
inflater.write(lineCount);
lineCount++;
}
inflater.write(fileByte);
}
inflater.flush();
outputBuff.flush();
fileOutputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}

Categories

Resources