Getting Stream closed when reading/writing to file Java - java

I'm implementing a small tool in Java. I have a excel document and from every sheet I need to generate a .sql file. I've created an sql file model, which I have to read from for every excel sheet then replace a value and write it back to another .sql file. The problem is I use a for where I loop through my sheets and for every sheet I need to read that sql file, modify it and export it somewhere else. I get a "Stream closed" error, and I don't know how to close my buffer and/or my InputStream properly. Can you guys help me out with this ?
This is my code:
This gets everything from the file and converts it to a String
public String getString(InputStream is) throws IOException {
BufferedReader reader = null;
StringBuilder sb = new StringBuilder();
String line;
try {
reader = new BufferedReader(new InputStreamReader(is));
while ((line = reader.readLine()) != null) {
sb.append(line + System.lineSeparator());
}
} catch (IOException ex) {
ex.printStackTrace();
}
return sb.toString();
}
This is used to export the file
public void exportFile(String text, String path, String name, String extension) {
BufferedWriter output = null;
try {
File sqlFile = new File(path + name + extension);
output = new BufferedWriter(new FileWriter(sqlFile));
output.write(text);
} catch (IOException e) {
e.printStackTrace();
logger.severe("Unable to write to file!\n");
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
logger.severe("Unable to close buffer\n");
}
}
}
}
And this a the part of my run() method, which uses the code above:
ClassLoader loader = this.getClass().getClassLoader();
InputStream createTableInputStream = loader.getResourceAsStream("val_table_create.sql");
if (createTableInputStream == null) {
logger.severe("No tempalte found for creating table!\n");
return;
}
List<Sheet> bookSheets = getSheets(book);
for (Sheet sheet : bookSheets) {
setHeader(table, sheet);
String exportText = getString(createTableInputStream);
exportText = exportText.replaceAll(TABLE_NAME, tableName);
// exportText = exportText.replaceAll(VAL_DATA_TYPE, valDataType);
// exportText = exportText.replaceAll(MSG_TEXT_DATA_TYPE, messageDataType);
exportFile(exportText, absoluteWorkspacePath + File.separator + outputPath + File.separator, tableName, ".sql");
}
if (createTableInputStream != null) {
createTableInputStream.close();
}

The Problem is in this method:
public String getString(InputStream is) throws IOException {
You close the the reader and stream at the end. (When you close the reader the streams in it are automatic close.
Edit: You should close the reader. getString(InputStream is) throws IOException returns always the same String or? Read it before you go in the loop and reuse the String everytime.
String exportText = getString("val_table_create.sql");
for (Sheet sheet : bookSheets) {
setHeader(table, sheet);
String newExportText = exportText.replaceAll(TABLE_NAME, tableName);
messageDataType);
exportFile(newExportText, absoluteWorkspacePath + File.separator + outputPath + File.separator, tableName, ".sql");
}
Change your getString Method to this:
public String getString(String resourceName) throws IOException {
BufferedReader reader = null;
StringBuilder sb = new StringBuilder();
String line;
try {
InputStream createTableInputStream reader.getResourceAsStream(resourceName);
reader = new BufferedReader(new InputStreamReader(is));
while ((line = reader.readLine()) != null) {
sb.append(line + System.lineSeparator());
}
} catch (IOException ex) {
ex.printStackTrace();
}
return sb.toString();
}
and close there all the streams. Now you have one place where you load your file.

createTableInputStream will be closed for the first time you call getString method so for next sheet in loop you will get stream closed.
It's a better practice to close the stream in the method who created it. You should close the stream in run method instead.

Related

Vaadin Upload Component output stream encoding issue?

forgive me if this has been discussed in the forum but I have been looking for answers to my problem.
I may not fully understand how the upload component is working. I plan to save a file to my server that I can later read the contents of into a table or text area.
This is my receive upload file method, where I am writing to a File and returning the FileOutputStream.
public OutputStream receiveUpload(String filename, String mimeType) {
// Create upload stream
FileOutputStream fos = null; // Stream to write to
try {
// Open the file for writing.
outputFile = new File("/tmp/" + filename);
fos = new FileOutputStream(outputFile);
} catch (final java.io.FileNotFoundException e) {
new Notification("Could not open file<br/>",
e.getMessage(),
Notification.Type.ERROR_MESSAGE)
.show(Page.getCurrent());
return null;
}
return fos; // Return the output stream to write to
}
This is my code once the upload succeeds
public void uploadFinished(Upload.FinishedEvent finishedEvent) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(outputFile.getAbsolutePath()), StandardCharsets.UTF_8));
String line;
while ((line = reader.readLine()) != null)
{
textArea.setValue(textArea.getValue() + "\n" + line);
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
This all works and outputs the contents of a file, eg PDF or Text file, but the contents are all wrapped with odd encoding such as
{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\paperw11900\paperh16840\margl1440\margr1440\vieww10800\viewh8400\viewkind0
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural
\f0\fs24 \cf0 hi there\ \ bye}
where the original file held
hi there
bye
What am I doing to include all the metadata etc?
Also Id like to note I added the standardcharset.UTF8 to the input stream in hope to fix this, but it is the exact same as without including this.
It appears the file is not a text file, but a PDF file. In your uploadFinished() method, you could first test the file type using https://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#probeContentType(java.nio.file.Path). If the file is a PDF, you can use PDFBox (How to read PDF files using Java?) to read the content, or if it is plain text, you can read it as you already are.
import java.nio.file.Files;
import java.nio.file.Path;
...
String contentType = Files.probeContentType(outputFile.toPath());
if(contentType.equals("application/pdf"))
{
PDDocument document = null;
document = PDDocument.load(outputFile);
document.getClass();
if( !document.isEncrypted() ){
PDFTextStripperByArea stripper = new PDFTextStripperByArea();
stripper.setSortByPosition( true );
PDFTextStripper Tstripper = new PDFTextStripper();
String st = Tstripper.getText(document);
textArea.setValue(st);
}
}catch(Exception e){
e.printStackTrace();
}
}
else if(contentType.equals("text/plain"))
{
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(outputFile.getAbsolutePath()), StandardCharsets.UTF_8));
String line;
while ((line = reader.readLine()) != null)
{
textArea.setValue(textArea.getValue() + "\n" + line);
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}

i want to change the text in a file, my code is searching the word but not replacing the word

I am trying to replace a string from a js file which have content like this
........
minimumSupportedVersion: '1.1.0',
........
now 'm trying to replace the 1.1.0 with 1.1.1. My code is searching the text but not replacing. Can anyone help me with this. Thanks in advance.
public class replacestring {
public static void main(String[] args)throws Exception
{
try{
FileReader fr = new FileReader("G:/backup/default0/default.js");
BufferedReader br = new BufferedReader(fr);
String line;
while((line=br.readLine()) != null) {
if(line.contains("1.1.0"))
{
System.out.println("searched");
line.replace("1.1.0","1.1.1");
System.out.println("String replaced");
}
}
}
catch(Exception e){
e.printStackTrace();
}
}
}
First, make sure you are assigning the result of the replace to something, otherwise it's lost, remember, String is immutable, it can't be changed...
line = line.replace("1.1.0","1.1.1");
Second, you will need to write the changes back to some file. I'd recommend that you create a temporary file, to which you can write each `line and when finished, delete the original file and rename the temporary file back into its place
Something like...
File original = new File("G:/backup/default0/default.js");
File tmp = new File("G:/backup/default0/tmpdefault.js");
boolean replace = false;
try (FileReader fr = new FileReader(original);
BufferedReader br = new BufferedReader(fr);
FileWriter fw = new FileWriter(tmp);
BufferedWriter bw = new BufferedWriter(fw)) {
String line = null;
while ((line = br.readLine()) != null) {
if (line.contains("1.1.0")) {
System.out.println("searched");
line = line.replace("1.1.0", "1.1.1");
bw.write(line);
bw.newLine();
System.out.println("String replaced");
}
}
replace = true;
} catch (Exception e) {
e.printStackTrace();
}
// Doing this here because I want the files to be closed!
if (replace) {
if (original.delete()) {
if (tmp.renameTo(original)) {
System.out.println("File was updated successfully");
} else {
System.err.println("Failed to rename " + tmp + " to " + original);
}
} else {
System.err.println("Failed to delete " + original);
}
}
for example.
You may also like to take a look at The try-with-resources Statement and make sure you are managing your resources properly
If you're working with Java 7 or above, use the new File I/O API (aka NIO) as
// Get the file path
Path jsFile = Paths.get("C:\\Users\\UserName\\Desktop\\file.js");
// Read all the contents
byte[] content = Files.readAllBytes(jsFile);
// Create a buffer
StringBuilder buffer = new StringBuilder(
new String(content, StandardCharsets.UTF_8)
);
// Search for version code
int pos = buffer.indexOf("1.1.0");
if (pos != -1) {
// Replace if found
buffer.replace(pos, pos + 5, "1.1.1");
// Overwrite with new contents
Files.write(jsFile,
buffer.toString().getBytes(StandardCharsets.UTF_8),
StandardOpenOption.TRUNCATE_EXISTING);
}
I'm assuming your script file size doesn't cross into MBs; use buffered I/O classes otherwise.

Writing multiple queries from a test file

public static void main(String[] args) {
ArrayList<String> studentTokens = new ArrayList<String>();
ArrayList<String> studentIds = new ArrayList<String>();
try {
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream(new File("file1.txt"));
BufferedReader br = new BufferedReader(new InputStreamReader(fstream, "UTF8"));
String strLine;
// Read File Line By Line
while ((strLine = br.readLine()) != null) {
strLine = strLine.trim();
if ((strLine.length()!=0) && (!strLine.contains("#"))) {
String[] students = strLine.split("\\s+");
studentTokens.add(students[TOKEN_COLUMN]);
studentIds.add(students[STUDENT_ID_COLUMN]);
}
}
for (int i=0; i<studentIds.size();i++) {
File file = new File("query.txt"); // The path of the textfile that will be converted to csv for upload
BufferedReader reader = new BufferedReader(new FileReader(file));
String line = "", oldtext = "";
while ((line = reader.readLine()) != null) {
oldtext += line + "\r\n";
}
reader.close();
String newtext = oldtext.replace("sanid", studentIds.get(i)).replace("salabel",studentTokens.get(i)); // Here the name "sanket" will be replaced by the current time stamp
FileWriter writer = new FileWriter("final.txt",true);
writer.write(newtext);
writer.close();
}
fstream.close();
br.close();
System.out.println("Done!!");
} catch (Exception e) {
e.printStackTrace();
System.err.println("Error: " + e.getMessage());
}
}
The above code of mine reads data from a text file and query is a file that has a query in which 2 places "sanid" and "salabel" are replaced by the content of string array and writes another file final . But when i run the code the the final does not have the queries. but while debugging it shows that all the values are replaced properly.
but while debugging it shows that all the values are replaced properly
If the values are found to be replaced when you debugged the code, but they are missing in the file, I would suggest that you flush the output stream. You are closing the FileWriter without calling flush(). The close() method delegates its call to the underlying StreamEncoder which does not flush the stream either.
public void close() throws IOException {
se.close();
}
Try this
writer.flush();
writer.close();
That should do it.

I am trying to modify some lines in text files and when I write that line back again to the file, I end up with a blank file

This code is reading a bunch of .java files and finding "public [classname]" or "private [classname]" and adding "System.out.println([classname])" to that line.
The problem is When I write that line back in I end up with a blank file
Can anyone see what I am doing wrong?
private static void work(ArrayList<File> fileList) {
for (int i = 0; i < fileList.size(); i++) {
replaceLines(fileList.get(i));
}
}
public static void replaceLines(File file) {
String path = file.getPath();
String fileNameLong = file.getName();
String fileName = null;
if (fileNameLong.contains(".java")) {
fileName = fileNameLong.substring(0, file.getName().indexOf("."));
}
if (fileName != null && fileName != "") {
System.out.println(fileName);
try {
//prepare reading
FileInputStream in = new FileInputStream(path);
BufferedReader br = new BufferedReader(
new InputStreamReader(in));
//prepare writing
FileWriter fw = new FileWriter(file);
PrintWriter out = new PrintWriter(fw);
String strLine;
while ((strLine = br.readLine()) != null) {
// Does it contain a public or private constructor?
boolean containsPrivateCon = strLine.contains("private "
+ fileName);
boolean containsPublicCon = strLine.contains("public "
+ fileName);
if (containsPrivateCon || containsPublicCon) {
int lastIndexOfBrack = strLine.lastIndexOf("{");
while (lastIndexOfBrack == -1) {
strLine = br.readLine();
lastIndexOfBrack = strLine.lastIndexOf("{");
}
if (lastIndexOfBrack != -1) {
String myAddition = "\n System.out.println(\""
+ fileName + ".java\"); \n";
String strLineModified = strLine.substring(0,
lastIndexOfBrack + 1)
+ myAddition
+ strLine.substring(lastIndexOfBrack + 1);
strLine = strLineModified;
}
}
out.write(strLine);
}
} catch (Exception e) {
System.out.println(e);
}
}
}
If you want to write to the same file you're reading from, you should either write to a copy of the file (different filename) and then rename the output file, or use RandomAccessFile interface to edit a file in-place.
Usually, the first solution will be much easier to implement than the second one; unless the files are huge (which is probably not the case with .java files), there is no real reason to use the second.
You forgot to flush and close the file. PrintWriter keeps a buffer and unless you explicitly flush() it, the data will (un)happily sit in the buffer and it will never be written to the output.
So you need to add this before the line catch (Exception e) {
out.flush();
out.close();
Note that this is only necessary for PrintWriter and PrintStream. All other output classes flush when you close them.

Return the text of a file as a string? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to create a Java String from the contents of a file
Is it possible to process a multi-lined text file and return its contents as a string?
If this is possible, please show me how.
If you need more information, I'm playing around with I/O. I want to open a text file, process its contents, return that as a String and set the contents of a textarea to that string.
Kind of like a text editor.
Use apache-commons FileUtils's readFileToString
Check the java tutorial here -
http://download.oracle.com/javase/tutorial/essential/io/file.html
Path file = ...;
InputStream in = null;
StringBuffer cBuf = new StringBuffer();
try {
in = file.newInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
cBuf.append("\n");
cBuf.append(line);
}
} catch (IOException x) {
System.err.println(x);
} finally {
if (in != null) in.close();
}
// cBuf.toString() will contain the entire file contents
return cBuf.toString();
Something along the lines of
String result = "";
try {
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
dis = new DataInputStream(bis);
while (dis.available() != 0) {
// Here's where you get the lines from your file
result += dis.readLine() + "\n";
}
fis.close();
bis.close();
dis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
String data = "";
try {
BufferedReader in = new BufferedReader(new FileReader(new File("some_file.txt")));
StringBuilder string = new StringBuilder();
for (String line = ""; line = in.readLine(); line != null)
string.append(line).append("\n");
in.close();
data = line.toString();
}
catch (IOException ioe) {
System.err.println("Oops: " + ioe.getMessage());
}
Just remember to import java.io.* first.
This will replace all newlines in the file with \n, because I don't think there is any way to get the separator used in the file.

Categories

Resources