url.openStream() to Writer - java

What is the correct way to write from an OutputStream (url.openStream()) to a Writer (it can be a FileWriter or a Stringwriter) without loosing encoding/charset??
public static String parseURLContentIntoFile(final URL url, final File fileToFill) throws IOException{
return parseURLContentIntoOutputWriter(url, new OutputStreamWriter(FileUtils.openOutputStream(fileToFill),"UTF-8"));
}
public static String parseURLContentIntoString(final URL url) throws IOException{
final StringWriter output = new StringWriter(); // Or StringBuilderWriter
parseURLContentIntoOutputWriter(url, output);
return output.getBuffer().toString(); //Or output.getBuilder().toString()
}
private static String parseURLContentIntoOutputWriter(final URL url, final Writer writer) throws IOException{
InputStreamReader in = null;
BufferedWriter out = null;
try {
out = new BufferedWriter(writer);
in = new InputStreamReader(url.openStream(),"UTF-8");
for(String line : IOUtils.readLines(in)){ //Uses a buffer internally
(...VERY LONG parsing...)
if (!line.isEmpty()) IOUtils.write(line,out);
}
(...Exception handling and stream closing...)
}
Thanks!

Related

How to process files for unit testing?

I have 5 input files in a folder, for each input file (1.in for example), I process it and produce a new output file (1.out) printing a integer in it.
How do I do this?
Right now this is what I have, I want to run different files like a2.in and print output in new file like a2.out (name them based on the input file names).
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("a1.in"));
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter("a1.out")));
public int compareTo(Event a) {
return ans;
}
That depends on unit test and assertion library you are using, below is example for junit-jupiter akin junit5 and assertJ:
#ParameterizedTest
#CsvSource(delimiterString = ";", value = {"a1.in;a1.out", "a2.in;a2.out""})
void test(String input, String output) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (InputStream in = getStream(input); InputStream expected = getStream(output)) {
// test body reading from in and writing to baos
assertThat(new ByteArrayInputStream(baos.toByteArray()))
.hasSameContentAs(expected);
}
}
InputStream getStream(String resource) {
return getClass().getResourceAsStream("/" + resource);
}
UPD (Thanks Reinier for comments).
If your goal is to test #main method (i.e. you are writing CLI application, which reads and writes some files) and your #main method looks like:
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(args[0]));
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(args[2])));
// do something with br and pw
}
consider redesigning it to something like:
public static void main(String[] args) throws IOException {
main(Files.newInputStream(Paths.get(args[0])), Files.newOutputStream(Paths.get(args[1])));
}
public static void main(InputStream in, OutputStream out) throws IOException {
try (
BufferedReader br = new BufferedReader(new InputStreamReader(in));
PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out);
) {
// do something with br and pw
pw.flush();
}
}
in that case the testability of #main method gets improved.

Multipart post of xlsx get corrupted via HTTPUrlConnection

I am trying to post xlsx file via HTTPUrlconnection, on receiving end I got the file but while opening it in MS Excel its saying that file is corrupted and repairing required . My code snippet for multipart post
class MultipartUtility {
private final Logger log = getLogger(MultipartUtility.class.getName());
private static final String CRLF = "\r\n";
private static final String CHARSET = "UTF-8";
private static final int CONNECT_TIMEOUT = 1500000;
private static final int READ_TIMEOUT = 1000000;
private final HttpURLConnection connection;
private final OutputStream outputStream;
private final PrintWriter writer;
private final String boundary;
// for log formatting only
private final URL url;
private final long start;
public MultipartUtility(final String strUrl) throws IOException {
start = currentTimeMillis();
URL url = new URL(strUrl);
this.url = url;
boundary = "---------------------------" + currentTimeMillis();
connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(CONNECT_TIMEOUT);
connection.setReadTimeout(READ_TIMEOUT);
connection.setRequestMethod("POST");
connection.setRequestProperty("Accept-Charset", CHARSET);
connection.setRequestProperty("Content-Type","multipart/form-data; boundary=" + boundary);
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(true);
outputStream = connection.getOutputStream();
writer = new PrintWriter(new OutputStreamWriter(outputStream, CHARSET),true);
}
public void addFilePart(final String filePath)throws IOException {
String fieldName = "content";
File uploadFile = new File(filePath);
final String fileName = uploadFile.getName();
writer.append("--").append(boundary).append(CRLF)
.append("Content-Disposition: form-data; name=\"")
.append(fieldName).append("\"; filename=\"").append(fileName)
.append("\"").append(CRLF).append("Content-Type: ")
.append(guessContentTypeFromName(fileName)).append(CRLF)
.append("Content-Transfer-Encoding: binary").append(CRLF)
.append(CRLF);
writer.flush();
outputStream.flush();
try (final FileInputStream inputStream = new FileInputStream(uploadFile);) {
final byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
}
writer.append(CRLF);
}
public HashMap<Object, Object> finish() throws IOException {
writer.append(CRLF).append("--").append(boundary).append("--").append(CRLF);
writer.close();
final int status = connection.getResponseCode();
if (status != HTTP_OK) {
throw new IOException(format("{0} failed with HTTP status: {1}",url, status));
}
try (final InputStream is = connection.getInputStream()) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String sResponse;
StringBuilder responseBuilder = new StringBuilder();
while ((sResponse = reader.readLine()) != null) {
responseBuilder = responseBuilder.append(sResponse);
}
HashMap respMap = new HashMap();
respMap.put("RESP_MSG", responseBuilder.toString());
respMap.put("RESP_CODE", status);
respMap.put("RESP_SIZE", responseBuilder.toString().length());
log.log(INFO,format("{0} took {4} ms", url,(currentTimeMillis() - start)));
log.log(INFO,"status::::::"+status);
return respMap;
} finally {
connection.disconnect();
}
}
}
The problem is with your addFilePart method, in the end, you are appending "writer.append(CRLF)"
when the number of files is one you should not add this at the end because it will add extra 2 bits to you file size you are sending over the network which is causing you xlxs file to get corrupted.
below is the code if you want to add one file or multiple files.
in this, we are appending CRLF(to separate the files) to the writer to all the files except the last one.
public void addFilePart(List<String> files) {
if (nonNull(files) && !files.isEmpty()) {
AtomicInteger counter = new AtomicInteger(0);
files.forEach(file -> {
try {
int i = counter.incrementAndGet();
this.addFilePart(file); // your add file part method
if (files.size() != i) {
writer.append(CRLF);
}
writer.flush();
} catch (IOException e) {
}
});
}
}
I tried to execute your code and was able to successfully upload file from java program.
The problem you reported is i guess due to content-type of the file. If you try to upload .xlsx (MS Excel 2007) it deforms the data and need to recover before we read uploaded file.
If you try to upload .xls file, it uploads properly without any deform and MS excel open this file without any warning/error.
So i would suggest to play around
writer.append(
"Content-Type: "
+ "application/x-excel")
to find the correct content-type refer to :
https://www.codeproject.com/Questions/481262/contentplustypeplusforplusxlsxplusfile
best of luck

Can't read objects from file and place them to linkedlist in java

I want to read object from a file and place data to a LinkedList and return the reference to it. But when I try this method it returns LinkedList that have no data.
private static LinkedList<Course> readFromFile(String fileName)
throws FileNotFoundException, IOException {
LinkedList<Course> tmp = new LinkedList<Course>();
reader = new ObjectInputStream(new FileInputStream(fileName));
try {
LinkedList<Course> readObject2 = (LinkedList<Course>) reader
.readObject();
LinkedList<Course> readObject = readObject2;
tmp = readObject;
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return tmp;
}
My writing method looks like this
private static boolean writeToFile(String fileName, LinkedList<Course> templist)
throws IOException {
LinkedList<Course> templist1 = new LinkedList<Course>();
if (createFile(fileName)) {
FileOutputStream outF = new FileOutputStream(fileName);
outO = new ObjectOutputStream(outF);
outO.writeObject(templist1);
//outO.flush();
return true;
}
else
return false;
}
Writing method looks like this
private static boolean writeToFile(String fileName, LinkedList<Course> templist) throws IOException {
LinkedList<Course> templist1 = new LinkedList<Course>();
if (createFile(fileName)) {
FileOutputStream outF = new FileOutputStream(fileName);
outO = new ObjectOutputStream(outF);
outO.writeObject(templist1);
//outO.flush();
return true;
}
else
return false;
}
The Course class is implementing java.io.Serializable ?
When you read objects from a file with ObjectInputStream it should be in the same order that you stored it with ObjectOutputStream before. And with the same objects types.
If you try to read:
(LinkedList<Course>) reader.readObject();
You must have store it like:
ObjectOutputStream writer = new ObjectOutputStream(
new FileOutputStream(fileName));
writer.writeObject(yourLinkedListToSave);
As your code looks:
private static boolean writeToFile(String fileName, LinkedList<Course> templist) throws IOException {
// Dont forget to initialize with your list else the list still empty
LinkedList<Course> templist1 = new LinkedList<Course>(templist);
if (createFile(fileName)) {
FileOutputStream outF = new FileOutputStream(fileName);
outO = new ObjectOutputStream(outF);
outO.writeObject(templist1);
//outO.flush();
return true;
}
else
return false;
}

Howto save HashSet<String> to .txt?

I want to store the HashSet to the server directory.
But i'm now only been able to store it in .bin files.
But how do I print all the Key's in the HashSet to a .txt file?
static Set<String> MapLocation = new HashSet<String>();
try {
SLAPI.save(MapLocation, "MapLocation.bin");
} catch (Exception ex) {
}
public static void save(Object obj, String path) throws Exception {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
path));
oos.writeObject(obj);
oos.flush();
oos.close();
}
// check IOException in method signature
BufferedWriter out = new BufferedWriter(new FileWriter(path));
Iterator it = MapLocation.iterator(); // why capital "M"?
while(it.hasNext()) {
out.write(it.next());
out.newLine();
}
out.close();
This will save the strings to a UTF-8 text file:
public static void save(Set<String> obj, String path) throws Exception {
PrintWriter pw = null;
try {
pw = new PrintWriter(
new OutputStreamWriter(new FileOutputStream(path), "UTF-8"));
for (String s : obj) {
pw.println(s);
}
pw.flush();
} finally {
pw.close();
}
}
Specifically choosing UTF-8 is desirable because otherwise it will use whatever setting the operating system uses as its default, which will give you compatibility headaches.
Something like this:
public static void toTextFile(String fileName, Set<String> set){
Charset charset = Charset.forName("UTF-8");
try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(fileName, charset))) {
for(String content: set){
writer.println(content);
}
} catch (IOException x) {
System.err.format("IOException: %s%n", x);
}
}
Note: This code is written using the try-with-resource construct introduced in Java 7. But the idea would remain the same for other versions as well.
Another solution that avoids a line break at the end of the file:
private static void store(Set<String> sourceSet, String targetFileName) throws IOException
{
StringBuilder stringBuilder = new StringBuilder();
for (String setElement : sourceSet)
{
stringBuilder.append(setElement);
stringBuilder.append(System.lineSeparator());
}
String setString = stringBuilder.toString().trim();
byte[] setBytes = setString.getBytes(StandardCharsets.UTF_8);
Files.write(Paths.get(targetFileName), setBytes);
}

java write data to file without erasing the old content

how can i
write data to file without erasing the old content
Use new FileOutputStream(file, true). This will open file in "append" mode which will append all data written to the stream to the end of that file.
You mean "how do you append to a file"? Look for an [append-version of a constructor][1] of your File writing class, e.g.:
public FileWriter(String fileName,
boolean append)
throws IOException
Use this constructor and pass true for the append parameter.
[1]: http://download.oracle.com/javase/6/docs/api/java/io/FileWriter.html#FileWriter(java.io.File, boolean)
if you used the new one in Java 7, you can use this way
try (BufferedWriter writer = Files.newBufferedWriter(outFile, StandardCharsets.UTF_8, StandardOpenOption.APPEND))
in this code i use append (true) but my old date erase and new data overwrite on it please give me solution on it
public class FileOperation {
private static FileReader fileReader;
private static FileWriter fileWriter;
private static BufferedReader bufferedReader;
private static BufferedWriter bufferedWriter;
private static PrintWriter writer;
public static File file = new File("C:\\StudentInfo\\com\\education\\students\\file\\managing\\v1_0\\Student.txt");
public FileOperation() throws IOException {
fileReader = new FileReader(file);
fileWriter = new FileWriter(file, true);
bufferedReader = new BufferedReader(fileReader);
bufferedWriter = new BufferedWriter(fileWriter);
// FileOperation fo =new FileOperation();
}
public boolean enrollSudnents(ArrayList<Student> studentList) {
try {
writer = new PrintWriter(file);
writer.print("");
bufferedWriter = new BufferedWriter(new FileWriter(file));
for (Student s : studentList) {
String nameNumberString = String.valueOf(s.getRoll() + "!" + s.getFirstName() + "!" + s.getLastName()
+ "!" + s.getClassName() + "!" + s.getAddress() + "\n");
bufferedWriter.write(nameNumberString);
}
return true;
} catch (Exception e) {
return false;
} finally {
try {
bufferedWriter.close();
fileWriter.close();
} catch (Exception e) {
// logger.info("Exception Found In Adding data");
}
}
}

Categories

Resources