Why is the file Read-Only? - java

I have got a Microsoft Access database in the resource folder of my Java application.
When the user clicks a button, this database is copied to the temp directory of the PC. Then I make a temporary VBS file in the same directory and execute it.
(This VBS file calls a VBA macro within the database, that deletes some records.)
However, as the macro attempts to delete the records an error is thrown stating that the database is read only.
Why does this happen?
Here is my code:
When the user clicks the button, some variables are set and then the following code is executed:
private void moveAccess() throws IOException {
String dbName = "sys_cl_imp.accdb";
String tempDbPath = System.getenv("TEMP").replace('\\', '/') + "/" + dbName;
InputStream in = ConscriptioLegere.class.getResourceAsStream("res/" + dbName);
File f = new File(tempDbPath);
Files.copy(in, f.toPath(), StandardCopyOption.REPLACE_EXISTING);
this.dbFilePath = tempDbPath;
System.out.println("access in temp");
f = null;
}
Then a connection is made to the database to update some data;
with
Connection con = DriverManager.getConnection("jdbc:ucanaccess://" + dbFilePath);
Statement sql = con.createStatement();
...
sql.close();
con.close();
Afterwards this is executed:
public boolean startImport() {
File vbsFile = new File(vbsFilePath);
PrintWriter pw;
try {
updateAccess();
} catch (IOException e) {
e.printStackTrace();
return false;
}
try{
pw = new PrintWriter(vbsFile);
pw.println("Set accessApp = CreateObject(\"Access.Application\")");
pw.println("accessApp.OpenCurrentDatabase (\"" + dbFilePath + "\")");
pw.println("accessApp.Run \"sys_cl_imp.importData\", \"" + saveLoc + "\"");
pw.println("accessApp.CloseCurrentDatabase");
pw.close();
Process p = Runtime.getRuntime().exec("cscript /nologo \"" + vbsFilePath + "\"");
While the process is running, the error occurres.
I don't understand why the database is open as ReadOnly.
I tried setting f to null after the copying of the db, but it proved not to work that way.

Based on this dicussion.
The solution is adding ;singleconnection=true to JDBC url. UCanAccess will close the file after JDBC connection closed.
Connection con = DriverManager.getConnection("jdbc:ucanaccess://" + dbFilePath +";singleconnection=true");

Thank you for your solution beckyang.
I managed to get it working with it, but there was a second mistake:
I deleted the contents of a table with java then closed the connection and run the vba procedure.
In the VBA I was attempting to delete the data again; but as there were none, this didn't work out.
After deleting the SQL from the VBA, the project worked :)

Related

Exception: Operating System error code 3

I am doing text file bulk upload in SQL Server. Whenever i tries to upload the files, gets Following Exception:
[Microsoft] [ODBC SQL Server Driver] [SQL Server]Could not bulk insert
because file 'C:/Form/Input_File/Form.txt' could not be opened.
Operating System error code 3(The system cannot find the path
specified).
Please find the below code:
public void uploadFiles()
{
File dir = new File(inputFilesPath);
String[] children = dir.list();
String completePathFileName = "";
System.out.println(" Inside Upload ::");
String saveFileNames = "";
PreparedStatement prepStat;
DBConnection dbConnection=new DBConnection();
Connection conHandler= dbConnection.getConnection();
if(null!=conHandler)
System.out.println(" Clear ::"+conHandler);
try
{
if (children != null)
{
for (int i = 0; i < children.length; i++)
{
String filename = children[i];
System.out.println(" children[i]::"+children[i]);
// File is validated based on some business rules.
if (isValidFile(filename) == 1)
{
String[] fileSplit = filename.split("E");
String[] extnSplit = fileSplit[1].trim().split(".TXT");
completePathFileName += (completePathFileName.equals(""))
? extnSplit[0] : "^" + extnSplit[0];
saveFileNames += (saveFileNames.equals(""))
? filename : "," + filename;
System.out.println(extnSplit[0]);
}
else
{
inValidFileNames += (inValidFileNames.equals(""))
? filename : ";\n" + filename;
}
}
if (!completePathFileName.trim().equals(""))
{
System.out.println(completePathFileName);
prepStat = conHandler.prepareStatement("Exec StartFileImport ?");
prepStat.setString(1, completePathFileName);
prepStat.execute();
saveFileNameToDatabase(saveFileNames);
}
}
}
catch (SQLException sql)
{
System.out.println(sql.getMessage());
}
}
Getting Connection Object from the below code:
public Connection getConnection()
{
System.out.println("In side DB Connection...");
try{
// get a database connection
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
System.out.println("Before Driver");
conn= DriverManager.getConnection("jdbc:odbc:form26qa","form26","form26");
System.out.println("After Driver");
if(conn != null)
{
System.out.println("Connection established...");
}//if
else
{
System.out.println("Connection failed...");
}//else
}//try
catch(Exception e)
{
System.out.println("Exception ocurred..."+e);
e.printStackTrace();
}//catch
return conn;
}
Explanation:
I am reading files from the input path and tried to get the fileName and file path and uploading file into SQL Server.
Application is able to find the input file in the specified path. while uploading i am getting the above mentioned Exception
Please check and suggest me to fix the issue.
The file needs to be accessable on the server. The file path is
relative to the server, not your PC. Also, if you are trying to use a
share or a mapped drive it will not work. You need to use the UNC
path.
UNC Name Examples
\\teela\admin$ (to reach C:\WINNT)
\\teela\admin$\system32 (to reach C:\WINNT\system32)
\\teela\temp (to reach C:\temp)

Using java to read files having oracle BFILE datatype from database

I have a table which contains location to files on the external filesystem.
The datatype used for column containing file locations is BFILE.
How to read such files from the database using java?
Hi please read following post and this Link will be helpful
This sample demonstrates Oracle JDBC BFILE support. It illustrates filling a table with BFILEs and includes a utility for dumping the contents of a BFILE. For information on BFILEs.
/*
* This sample demonstrate basic File support
*/
import java.sql.*;
import java.io.*;
import java.util.*;
//including this import makes the code easier to read
import oracle.jdbc.driver.*;
// needed for new BFILE class
import oracle.sql.*;
public class FileExample{
public static void main (String args [])throws Exception{
// Register the Oracle JDBC driver
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
// Connect to the database
// You can put a database name after the # sign in the connection URL.
//
// The sample creates a DIRECTORY and you have to be connected as
// "system" to be able to run the test.
// I you can't connect as "system" have your system manager
// create the directory for you, grant you the rights to it, and
// remove the portion of this program that drops and creates the directory.
Connection conn =
DriverManager.getConnection ("jdbc:oracle:oci8:#", "system", "manager");
// It's faster when auto commit is off
conn.setAutoCommit (false);
// Create a Statement
Statement stmt = conn.createStatement ();
try
{
stmt.execute ("drop directory TEST_DIR");
}
catch (SQLException e)
{
// An error is raised if the directory does not exist. Just ignore it.
}
stmt.execute ("create directory TEST_DIR as '/tmp/filetest'");
try
{
stmt.execute ("drop table test_dir_table");
}
catch (SQLException e)
{
// An error is raised if the table does not exist. Just ignore it.
}
// Create and populate a table with files
// The files file1 and file2 must exist in the directory TEST_DIR created
// above as symbolic name for /private/local/filetest.
stmt.execute ("create table test_dir_table (x varchar2 (30), b bfile)");
stmt.execute ("insert into test_dir_table values
('one', bfilename ('TEST_DIR', 'file1'))");
stmt.execute ("insert into test_dir_table values
('two', bfilename ('TEST_DIR', 'file2'))");
// Select the file from the table
ResultSet rset = stmt.executeQuery ("select * from test_dir_table");
while (rset.next ())
{
String x = rset.getString (1);
BFILE bfile = ((OracleResultSet)rset).getBFILE (2);
System.out.println (x + " " + bfile);
// Dump the file contents
dumpBfile (conn, bfile);
}
// Close all resources
rset.close();
stmt.close();
conn.close();}
// Utility function to dump the contents of a Bfile
static void dumpBfile (Connection conn, BFILE bfile) throws Exception{
System.out.println ("Dumping file " + bfile.getName());
System.out.println ("File exists: " + bfile.fileExists());
System.out.println ("File open: " + bfile.isFileOpen());
System.out.println ("Opening File: ");
bfile.openFile();
System.out.println ("File open: " + bfile.isFileOpen());
long length = bfile.length();
System.out.println ("File length: " + length);
int chunk = 10;
InputStream instream = bfile.getBinaryStream();
// Create temporary buffer for read
byte[] buffer = new byte[chunk];
// Fetch data
while ((length = instream.read(buffer)) != -1)
{
System.out.print("Read " + length + " bytes: ");
for (int i=0; i<length; i++)
System.out.print(buffer[i]+" ");
System.out.println();
}
// Close input stream
instream.close();
// close file handler
bfile.closeFile();}}
Use the following link
https://docs.oracle.com/cd/A97335_02/apps.102/a83724/oralob3.htm#1059336
There you will find many examples like this
OraclePreparedStatement ops = (OraclePreparedStatement)conn.prepareStatement
("INSERT INTO my_bfile_table VALUES (?,?)");
ops.setString(1,"one");
ops.setBFILE(2, bfile);
ops.execute();

Making Oracle DB connection Dynnamically in JSP

Connecting to database dynamically jsp
Hi, I'm trying to make connection to database dynamically.
So when user clicks link from index page, it will send parameter "OS"
so my test page will receive parameter OS, looks for matchs in textfile that has list of database information like
XP-jdbc:oracle:thin#xx.xxx.xx.xx:xxxx:XPXP1-XP_user-XP_pass
W7-jdbc:oracle:thin#YY.YYY.YY.YY:YYYY:W7W71-W7_user-W7_pass
MAC-jdbc:oracle:thin#ZZ.ZZZ.ZZ.ZZ:ZZZZ:MACO1-MAC_user-MAC_pass
LINNUX-jdbc:oracle:thin#AA.AAA.A.AA:AAAA:LINN1-LINNUX_user-LINNUX_ph1
my attempt:
String userName = request.getParameter("OS");
try{
String db = "";
String[] temp1;
String dblist = root + "\\" + "dblist.txt";
BufferedReader dbin = new BufferedReader(new FileReader(dblist));
while ((db = dbin.readLine()) != null){
temp1=db.split("-");
if ((temp1[0].equals(userName))){
connString = temp1[1].toString();
connUser = temp1[2].toString();
connPass = temp1[3].toString();
}
}
dbin.close();
}catch (IOException ex) {
System.out.println(ex);
}
try{
DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
Connection conn = DriverManager.getConnection(connString, connUser, connPass);
Statement stmt = conn.createStatement();
}
My problem is, this doesn't work!
I get java.sql.SQLException: Invalid Oracle URL specified when i open my web page....
What did i have wrong?
Apparently my property file was corrutped >.> that was the reason why my property file only read half of it's components...thanks for your help anyways
you could use Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); instead of DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
Also,have you checked if YY.YYY.YY.YY:YYYY is replaced by proper IP and port?

Executing a .sql file through Java

I have a sql script file, i need to execute commands present in that through java. I searched in internet regarding the same, i got some code defining parsers to split the SQL statements and executing that. But none of them worked for my sql script file.Because my script file contains both create statements and alter statements without semicolon at the end[Instead it has GO]Can anybody suggest a solution to execute the script file?
Thanks,
Mahesh
For simple scripts I generally use this class from ibatis - ScriptRunner. Alternative you can spawn a new db client process from Java and feed in the script you wan't execute. This will work for all scripts, as simple solutions like ScriptRunner don't work well when the delimiters in the sql files get changed for instance.
Here's an example how to feed the sql as a string to a spawed db client process:
private void runSql(String pSql) {
String tCommand = "mysql -u " + username + (password != null ? " -p" + password : "") + " " + dbName;
System.out.println(tCommand);
try {
Process tProcess = Runtime.getRuntime().exec(tCommand);
OutputStream tOutputStream = tProcess.getOutputStream();
Writer w = new OutputStreamWriter(tOutputStream);
System.out.println(pSql);
w.write(pSql);
w.flush();
Scanner in = new Scanner(tProcess.getErrorStream());
String errorMessage = "";
while (in.hasNext()) {
errorMessage += in.next() + " ";
}
if (errorMessage.length() > 0) {
System.out.println(errorMessage);
throw new ClientSqlExecutionException(errorMessage);
}
} catch (IOException e) {
e.printStackTrace();
}
}
Have a look at Mybatis Migrations code, it does something like the one you need:
http://code.google.com/p/mybatis/wiki/Migration
You need to change the parser so it produces executable statements. But I'm not sure I understand what you mean when you say "execute through Java".
Java won't execute those SQL statements - the database you connect to will. Java can connect to a database using JDBC and send the SQL statements from the file.
I don't see why you have to parse the SQL, unless you want Java to validate them before sending them on to the database server. The server will parse and validate them again, so it feels like you're doing extra work for nothing.
The simplest solution I can present to you is this, presuming I understand your question.
1) Read text file into a string or array via Java IO.
2) Pass string or array to MySQL via JDBC.
Read from file example,
import java.io.*;
class FileRead
{
public static void main(String args[])
{
try{
// Open the file that is the first
// command line parameter
FileInputStream fstream = new FileInputStream("textfile.txt");
// Get the object of DataInputStream
DataInputStream in = new DataInputStream(fstream);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String strLine;
//Read File Line By Line
while ((strLine = br.readLine()) != null) {
// Print the content on the console
System.out.println (strLine);
}
//Close the input stream
in.close();
}catch (Exception e){//Catch exception if any
System.err.println("Error: " + e.getMessage());
}
}
}
acquired from, http://www.roseindia.net/java/beginners/java-read-file-line-by-line.shtml
The simplest way is to simply get the statements and check if they need they semi-column at the end: (this is an example and only works if it is a statement by line:
public void executeScript(String script) {
BufferedReader in = new BufferedReader(new FileReader(script));
while (in.read() > 0) {
String statement = in.readLine();
statement = statement.trim().toLowerCase();
String command = statement.split("[ ]+")[0]; // split the statement.
if (command.equals("insert") || command.equals("update") /* || any other */) {
statement = statement + ";";
}
// execute statement using jdbc
}
}
If you do not know how to use jdbc, just ask :-)
Use this slightly modified version of the com.ibatis.common.jdbc.ScriptRunner class which is fully self contained, i.e. you do not need to have any third party jar dependencies.
It is possible to change the delimiter from ; to GO. I think that should do the trick.
Here is an example:
Reader reader = new BufferedReader(*** Your FileReader instance ***);
try
{
ScriptRunner runner = new ScriptRunner(connection, false, true);
runner.setDelimiter("GO", true);
runner.runScript(reader);
}
finally
{
reader.close();
}
Apache Ant SQL Task worked for me.
https://ant.apache.org/manual/Tasks/sql.html

Difference in Reading .CSV file in UNIX System & Windows System

I have created a JSP code where we can upload a .csv file. The JSP Code is supported by a java code that reads the .csv file and compares the urls in the file with the DB and adds it into to the DB if the urls are not already present.
The above scenario works absolutely fine when its executed in a windows system.
I uploaded the succesfully executed web application folder to a unix system. When I executed the program in the UNIX system, the tool is not comparing the URLs with the DB and adds it.
I suspect there should be some problem in reading the .csv file in a UNIX sytem.
Am using fedora(linux) OS. Kindly let me know whether there is any differences in reading .csv file between a windows system and a unix system.
The .csv file I am using has the following contents,
http://www.topix.com,sdfasdf
http://rss.news.yahoo.com/rss/topstories,Apple
http://www.apple.com/354,sdfasdf
http://www.topix.com/rss/city/emporia-ks,sdfasdf
http://www.topix.com/rss/,sdfasdf
http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/ws/RSS/topsongs/limit=10/xml,sdfasdf
http://www.topix.com/rss/city/emp,sdfasdf
http://www.topix.com/rss/city/sandy-ut,dfgsdfg
http://www.apple.com,Yahoo
UPDATE FOR JEFF
try {
List items = uploadHandler.parseRequest(request);
Iterator itr = items.iterator();
while(itr.hasNext()) {
FileItem item = (FileItem) itr.next();
if(item.isFormField()) {
out.println("File Name = "+item.getFieldName()+", Value = "+item.getString());
} else {
File file = new File(destinationDir,item.getName());
item.write(file);
//String temp=item.getName();
String fileToBeRead = "C:/Program Files/Apache Software Foundation/Tomcat 5.5/webapps/Readcsv/files/"+item.getName();
String urlcnt="";
String srccnt="";
String contentType="";
Connection con=null;
Statement stmt=null;
final String rssvar="Rss";
final String other="Other";
int i=0;
int j=0;
try {
BufferedReader br = new BufferedReader(new FileReader(fileToBeRead));
String strLine = "";
StringTokenizer st = null;
while( (strLine = br.readLine()) != null)
{
st = new StringTokenizer(strLine, ",");
while(st.hasMoreTokens()){
urlcnt=st.nextToken();
srccnt=st.nextToken();
}
if(con==null){
SQLConnection.setURL("jdbc:sqlserver://192.168.2.53\\SQL2005;user=sa;password=365media;DatabaseName=LN_ADWEEK");
con=SQLConnection.getNewConnection();
stmt=con.createStatement();
}
try{
ResultSet rs;
boolean hasRows=false;
rs=stmt.executeQuery("select url from urls_linkins where url='"+urlcnt+"'");
while(rs.next()){
hasRows=true;
i++;
}
if(!hasRows){
j++;
URL url = new URL(urlcnt);
URLConnection url1=url.openConnection();
contentType=url1.getContentType();
PreparedStatement insertUrlStatement = con.prepareStatement("INSERT INTO urls_linkins(url, source_name, is_active, is_periodic, Link_Type, New_Entry) VALUES(?, ?, ?, ?, ?, ?)");
if(contentType.contains("rss") || contentType.contains("xml"))
{
insertUrlStatement.setString(1, urlcnt);
insertUrlStatement.setString(2, srccnt);
insertUrlStatement.setInt(3, 1);
insertUrlStatement.setInt(4, 0);
insertUrlStatement.setString(5, rssvar);
insertUrlStatement.setInt(6, 1);
insertUrlStatement.executeUpdate();
insertUrlStatement.close();
}
else{
insertUrlStatement.setString(1, urlcnt);
insertUrlStatement.setString(2, srccnt);
insertUrlStatement.setInt(3, 1);
insertUrlStatement.setInt(4, 0);
insertUrlStatement.setString(5, other);
insertUrlStatement.setInt(6, 1);
insertUrlStatement.executeUpdate();
insertUrlStatement.close();
}
}
}
catch(Exception e){
e.printStackTrace();
}
}
}catch(Exception e){
e.printStackTrace();
}finally{
out.println("<h2>"+j+" url has been added and "+i+" url already exists in the DB</h2>");
out.println("<a href=Addurl.jsp>Check URL</a>");
out.println("<a href=Addurl1.jsp>Add Single URL</a>");
out.println("<a href=uploadcsv.jsp>Add Multiple URL</a>");
}
}
out.close();
}
}catch(FileUploadException ex) {
log("Error encountered while parsing the request",ex);
} catch(Exception ex) {
log("Error encountered while uploading file",ex);
}
This is my reading code of the .csv file.
Yes there will be differences in reading the .csv file when you transfer from a windows machine to a unix machine even when it's a text file. There are hidden space characters which may be represented differently on the unix machine.
I suspect that the reason it is not comparing the URLs is because the space characters might be different ASCII values so it thinks they are different and adds the URL into the DB.
One suggestion would be to use the dos2unix command.
http://kb.iu.edu/data/acux.html
Hope it helps.

Categories