I am doing some code that writes an Excel file. However, when opening the file created at the end of the main function, Open Office displays an error message that the file is locked by an unknown user. I checked and it seems I am closing all the references to the file and the workbook using the file.
Thanks in advance for any help!
Code
public class StandingsFile
{
private Workbook workbook;
public StandingsFile(InputStream inputStream, File outputFile)
{
this.outputFile = outputFile;
workbook = POIExcelFileProcessor.createWorkbook(inputStream);
}
public void write()
{
// Code where the sheets in the Excel file are modified
POIExcelFileProcessor.writeWorkbook(workbook, outputFile);
}
public static void main(String[] args)
{
standingsExcelFile = new StandingsFile(StandingsCreationHelper.class.getResourceAsStream(TEMPLATE_FILENAME), outputFile);
standingsExcelFile.write();
try
{
Desktop dt = Desktop.getDesktop();
dt.open(outputFile);
}
catch (Exception ex)
{
e.printStackTrace();
}
}
}
public class POIExcelFileProcessor
{
public static Workbook createWorkbook(InputStream inputStream)
{
Workbook workbook = null;
try
{
workbook = WorkbookFactory.create(inputStream);
}
catch (Exception e)
{
e.printStackTrace();
}
return workbook;
}
public static void writeWorkbook(Workbook workbook, File outputFile)
{
try
{
FileOutputStream fileOut = new FileOutputStream(outputFile);
workbook.write(fileOut);
fileOut.flush();
workbook.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
You need to remember to close the file when you're done with it, either explicitly with the close method (in a finally block) or with a try-with-resources statement.
This goes as a general rule, not just for using POI.
Related
I'm trying to read the contents of an excel worksheet but my method keeps throwing an exception. I've tried everything to no avail but i'm sure that its a very minor detail that i'm not seeing. Could someone look at my code with a fresh pair of eyes and possibly point me out to what i'm doing wrong. Thanks!
/**
* This method sets the path to the excel file and the excel sheet as well as
* initializing the stream
*/
public static void setExcelFile(String path, String sheetName) {
try {
FileInputStream excelFile = new FileInputStream(path);
workbook = new XSSFWorkbook(excelFile);
worksheet = workbook.getSheet(sheetName);
}
catch (Exception e) {
e.printStackTrace();
}
}
/**
* This method reads the cell data from the excel file
*/
public static String getCellData(int rowNum, int colNum) {
try {
//This is what is causing my nullpointerexception according to eclipse
row = worksheet.getRow(rowNum);
//cell = worksheet.getRow(rowNum).getCell(colNum);
cell = row.getCell(colNum);
String cellData = cell.getStringCellValue();
return cellData;
}
catch (Exception e) {
e.printStackTrace();
return "Lactoferrin";
}
}
/**
* This is how i call both methods
*/
public static void main(String[] args) {
try {
ExcelUtility.setExcelFile(PATHTOTESTDATA, FILENAME);
String cellContents = ExcelUtility.getCellData(1,0);
System.out.println(cellContents);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Found it. I had saved the excel file within a package with the class files and eclipse could not find it...I do not know why. So i moved it into a folder at the root of the project and it worked.
i try to put data in a template .xls file (it can be xlsx if necessary) using apache POI but i can't figure it out and the file is still unchanged . no exception thrown in PrintStackTrace . would you please provide me with a working code? i read so many documents so please help me with working code. thanks
my code :
final Button but = (Button) findViewById(R.id.bk);
but.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
writeXLSFile(3, 3);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
public static void writeXLSFile(int row, int col) throws IOException {
try {
FileInputStream file = new FileInputStream(Environment.getExternalStorageDirectory().toString() +"telegran/"+ "ex.xls");
HSSFWorkbook workbook = new HSSFWorkbook(file);
HSSFSheet sheet = workbook.getSheetAt(0);
Cell cell = null;
//Update the value of cell
cell = sheet.getRow(row).getCell(col);
cell.setCellValue("changed");
file.close();
FileOutputStream outFile =new FileOutputStream(new File(Environment.getExternalStorageDirectory().toString() +"telegran/"+ "ex.xls"));
workbook.write(outFile);
outFile.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
try to file.close(); after workbook.write(outFile); outFile.close();
I think the issue here is you are trying to get a row and a cell that were not created in the first place.
You need to create a Row first before calling cell = sheet.getRow(row); like
XSSFRow row = sheet.createRow(rowIndex);
And create a Cell as well like
Cell cell = row.createCell(cellIndex);
see this full example for more details
I've found answers to various questions on here before, but this is my first time asking one. I'm kicking around an idea for my final project in my computer programming class, and I'm working on a few proof of concept programs in Java, working in Eclipse. I don't need anything more than to get the filepaths of the contents of a directory and write them to a .txt file. Thanks in advance!
Edit: I am posting my code below. I found a snippet of code to use for getting the contents and print them to the screen, but the print command is a placeholder that I'll replace with a write to folder command when I can.
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class ScanFolder {
public static void main(String[] args) throws IOException {
Files.walk(Paths.get("C:/Users/Joe/Desktop/test")).forEach(filePath -> {
if (Files.isRegularFile(filePath)) {
System.out.println(filePath);
}
});
}
}
EDIT: I've enclosed the OutputStreamWriter in a BufferedWriter
public static void main(String[] args) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream("txt.txt");
} catch (FileNotFoundException e) {
e.printStackTrace();
return;
}
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(fos));
writeContentsOfFileToAFile(new File("."), out, true); // change true to
// false if you
// don't want to
// recursively
// list the
// files
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
static void writeContentsOfFileToAFile(File parent, BufferedWriter out, boolean enterIntoDirectory) {
for (File file : parent.listFiles()) {
try {
out.write(file.toString() + "\r\n");
} catch (IOException e) {
e.printStackTrace();
}
if (enterIntoDirectory && file.isDirectory())
writeContentsOfFileToAFile(file, out, enterIntoDirectory);
}
}
Is this what you need?
Okay, this is going to be a bit long. So I made a junit test class to test my program. I wanted to test if a method that uses a Scanner to read a file into the program threw and exception, if the file didn't exist like this:
#Test
public void testLoadAsTextFileNotFound()
{
File fileToDelete = new File("StoredWebPage.txt");
if(fileToDelete.delete()==false) {
System.out.println("testLoadAsTextFileNotFound - failed");
fail("Could not delete file");
}
try{
assertTrue(tester.loadAsText() == 1);
System.out.println("testLoadAsTextFileNotFound - passed");
} catch(AssertionError e) {
System.out.println("testLoadAsTextFileNotFound - failed");
fail("Did not catch Exception");
}
}
But the test fails at "could not delete file", so I did some searching. The path is correct, I have permissions to the file because the program made it in the first place. So the only other option would be, that a stream to or from the file is still running. So I checked the method, and the other method that uses the file, and as far as I can, both streams are closed inside the methods.
protected String storedSite; //an instance variable
/**
* Store the instance variable as text in a file
*/
public void storeAsText()
{
PrintStream fileOut = null;
try{
File file = new File("StoredWebPage.txt");
if (!file.exists()) {
file.createNewFile();
}
fileOut = new PrintStream("StoredWebPage.txt");
fileOut.print(storedSite);
fileOut.flush();
fileOut.close();
} catch(Exception e) {
if(e instanceof FileNotFoundException) {
System.out.println("File not found");
}
fileOut.close();
} finally {
if(fileOut != null)
fileOut.close();
}
}
/**
* Loads the file into the program
*/
public int loadAsText()
{
storedSite = ""; //cleansing storedSite before new webpage is stored
Scanner fileLoader = null;
try {
fileLoader = new Scanner(new File("StoredWebPage.txt"));
String inputLine;
while((inputLine = fileLoader.nextLine()) != null)
storedSite = storedSite+inputLine;
fileLoader.close();
} catch(Exception e) {
if(e instanceof FileNotFoundException) {
System.out.println("File not found");
return 1;
}
System.out.println("an Exception was caught");
fileLoader.close();
} finally {
if(fileLoader!=null)
fileLoader.close();
}
return 0; //return value is for testing purposes only
}
I'm out of ideas. Why can't I delete my file?
EDIT: i've edited the code, but still this give me the same problem :S
You have two problems here. The first is that if an exception is thrown during your write to the file, the output stream is not closed (same for the read):
try {
OutputStream someOutput = /* a new stream */;
/* write */
someOutput.close();
The second problem is that if there's an exception you aren't notified:
} catch (Exception e) {
if (e instanceof FileNotFoundException) {
/* do something */
}
/* else eat it */
}
So the problem is almost certainly that some other exception is being thrown and you don't know about it.
The 'correct' idiom to close a stream is the following:
OutputStream someOutput = null;
try {
someOutput = /* a new stream */;
/* write */
} catch (Exception e) {
/* and do something with ALL exceptions */
} finally {
if (someOutput != null) someOutput.close();
}
Or in Java 7 you can use try-with-resources.
I have an object in charge of opening a file on HDFS to write. This object renames the file it just wrote once the close() method is invoked.
The mechanism works when running in local mode, but it fails to rename the file in cluster mode.
//Constructor
public WriteStream() {
path = String.format("in_progress/file");
try {
OutputStream outputStream = fileSystem.create(new Path(hdfs_path+path), new Progressable() {public void progress() { System.out.print("."); }
});
writer = new BufferedWriter(new OutputStreamWriter(outputStream));
} catch (IOException e) {
e.printStackTrace();
}
}
public void close() {
String newPath = String.format("%s_dir/%s_file", date, timestamp);
try {
fileSystem.rename(new Path(hdfs_path+path), new Path(hdfs_path+newPath));
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Did you experience that before ?
Apparently FileSystem.rename(Path) creates missing directories on the path when executed in local mode, but it does not when run in cluster mode.
This code works in both modes:
public void close() {
String dirPath = String.format("%s_dir/", date, timestamp);
String newPath = String.format("%s_dir/%s_file", date, timestamp);
try {
fileSystem.mkdir(new Path(hdfs_path+dirPath));
fileSystem.rename(new Path(hdfs_path+path), new Path(hdfs_path+newPath));
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Just curious, but how can you rename a file that officially doesn't exist (because you're still writing at that point)?
The fix is to rename after the file has been completed. That is, when you invoked the close method.
So your code should look like this:
public void close() {
String newPath = String.format("%s_dir/%s_file", date, timestamp);
try {
writer.close();
fileSystem.rename(new Path(hdfs_path+path), new Path(hdfs_path+newPath));
} catch (IOException e) {
e.printStackTrace();
}
}