File naming error in Android - java

Hello all I am having a problem when exporting a named file to the device internal storage for my apps Sqlite database name.
I am getting the error
java.io.FileNotFoundException: /storage/emulated/0/Download/:/09/12/2017-JDO.db: open failed: ENOENT (No such file or directory)
when trying to name the file /09/12/2017-JDO.
I am using File.pathSeparator() with the passed in file name but still am not having any luck. I think it has to do with the / in the file name which is the reason why I tried the File.pathSeparator() to begin with since I want that option for naming the file if the user wants to include the date in that format or in combination with the /.
Here are some code snippets of the methods I am using to try and accomplish this and to show what I am trying to do.
/*
This method saves and exports the current database to the device's internal Downloads folder
This is the default named database
*/
public void backUpDatabase() {
/* Open your local db as the input stream */
DBHelper anotherDbHelper = null;
try {
try {
anotherDbHelper = new DBHelper(ExistingTallyActivity.this);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
String path = null;
if (anotherDbHelper != null) {
path = String.valueOf(getApplicationContext().getDatabasePath(anotherDbHelper.getDatabaseName()));
}
File dbFile = null;
if (path != null) {
dbFile = new File(path);
}
FileInputStream fis = null;
try {
if (dbFile != null) {
fis = new FileInputStream(dbFile);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
String outFileName = (Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + "/Pipe_Tally");
/* Open the empty db as the output stream */
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(outFileName);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
/* Transfer bytes from the input-file to the output-file */
byte[] buffer = new byte[1024];
int length;
try {
if (fis != null) {
while ((length = fis.read(buffer)) > 0) {
try {
if (outputStream != null) {
outputStream.write(buffer, 0, length);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
/* Close the streams */
try {
if (outputStream != null) {
outputStream.flush();
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
if (anotherDbHelper != null) {
anotherDbHelper.close();
}
}
/*
This method renames the database to what the user inputs they want. Note: The original db is
still present and stored in the Downloads folder as well.
*/
public void renameDbFile(String desiredDbName) {
/* Open your local db as the input stream */
DBHelper dbHelperToRename = null;
try {
try {
dbHelperToRename = new DBHelper(ExistingTallyActivity.this);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
String pathRenamed = null;
if (dbHelperToRename != null) {
pathRenamed = String.valueOf(getApplicationContext().getDatabasePath(dbHelperToRename.getDatabaseName()));
}
File dbFileRenamed = null;
if (pathRenamed != null) {
dbFileRenamed = new File(pathRenamed);
}
FileInputStream fisRenamed = null;
try {
if (dbFileRenamed != null) {
fisRenamed = new FileInputStream(dbFileRenamed);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
/* Here is where the db is renamed by the user by inserting the passed in string to the method */
String outFileNameRenamed =
(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
.getAbsolutePath() + "/"+desiredDbName+".db");
// Open the empty db as the output stream
OutputStream outputStreamRenamed = null;
try {
outputStreamRenamed = new FileOutputStream(outFileNameRenamed);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
/* Transfer bytes from the input-file to the output-file */
byte[] bufferRenamed = new byte[1024];
int length;
try {
if (fisRenamed != null) {
while ((length = fisRenamed.read(bufferRenamed)) > 0) {
try {
if (outputStreamRenamed != null) {
outputStreamRenamed.write(bufferRenamed, 0, length);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
/* Close the streams */
try {
if (outputStreamRenamed != null) {
outputStreamRenamed.flush();
outputStreamRenamed.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fisRenamed != null) {
fisRenamed.close();
}
} catch (IOException e) {
e.printStackTrace();
}
if (dbHelperToRename != null) {
dbHelperToRename.close();
}
}
/*
This method exports the database into CSV format as well by naming it the passed in string value
for the desired name.
*/
#TargetApi(Build.VERSION_CODES.KITKAT)
public void saveDbAsCsv(String desiredCsvName) {
/* Getting a instance of the DbHelper class right here. */
DBHelper dbhelperCsv = null;
try {
dbhelperCsv = new DBHelper(ExistingTallyActivity.this);
} catch (ClassNotFoundException | NoSuchFieldException e) {
e.printStackTrace();
}
/* Original name of the file dir where the db will be stored in csv format. (Just like SQLite) */
String pathRenamedCsv = null;
if (dbhelperCsv != null) {
pathRenamedCsv = String.valueOf(getApplicationContext().getDatabasePath(dbhelperCsv.getDatabaseName()));
}
/* Creating a File type here with the passed in name from above from the string */
File dbFile = getDatabasePath(pathRenamedCsv);
/*
Appending the desired name to the Downloads Directory here, which is where the new file
will be written
*/
String renamedCsvName = (Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + "/"+desiredCsvName);
File exportDir = new File(String.valueOf(renamedCsvName));
if (!exportDir.exists())
{
exportDir.mkdirs();
}
/*
Critical .csv extension here. Took me a while originally to figure out where to pass this
in at. Was at first passing it into the renamedCsvName up above and it was just returning
a folder with the .csv extension and not the file contained withn.
*/
File file = new File(exportDir, desiredCsvName+".csv");
try
{
/* Passing in the string value of the file to an instance of the CsvWriter class */
CsvWriter csvWriter = new CsvWriter(String.valueOf(file));
SQLiteDatabase db = null;
if (dbhelperCsv != null) {
db = dbhelperCsv.getReadableDatabase();
}
/* Getting a cursor from the database table Tally_File */
Cursor curCSV = null;
if (db != null) {
curCSV = db.rawQuery("SELECT * FROM Tally_File",null);
}
if (curCSV != null) {
csvWriter.writeRecord(curCSV.getColumnNames());
}
if (curCSV != null) {
while(curCSV.moveToNext())
{
/* Exporting all the columns here to write out to the csv file */
String arrStr[] ={curCSV.getString(0),curCSV.getString(1), curCSV.getString(2),
curCSV.getString(3), curCSV.getString(4), curCSV.getString(5),
curCSV.getString(6), curCSV.getString(7), curCSV.getString(8),
curCSV.getString(9), curCSV.getString(10), curCSV.getString(11),
curCSV.getString(12), curCSV.getString(13), curCSV.getString(14), curCSV.getString(15),
curCSV.getString(16)};
/*
Critical here as I was not at first calling the writeRecord that accepted the
String[] array and was calling the toString() method on it and only getting a large
array.
*/
csvWriter.writeRecord(arrStr);
}
}
csvWriter.close();
if (curCSV != null) {
curCSV.close();
}
}
catch(Exception sqlEx)
{
Toast.makeText(this, "Error naming file", Toast.LENGTH_LONG).show();
}
}
Here is where I am calling the methods and passing in the desiredName for naming the file/Db, which is switch case dependent on a menu selection, all within the same activity.
case R.id.menu_save_and_export:
Thread threadMenuSaveAndExport = new Thread();
/*
This method verifies user permissions then calls the backUpDatabase() method to
backup the original db file before the user renames it, if desired.
*/
verifyStoragePermissions(new Runnable() {
#Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
/* Calling this method here to backup the current database*/
backUpDatabase();
}
});
/* Loading the view of activity_database_name with this LayoutInflater*/
View view = LayoutInflater.from(ExistingTallyActivity.this)
.inflate(R.layout.activity_database_name,null);
/*This editText handles the input from the user for their chosen db name*/
mEtCustomDbName = (EditText) view.findViewById(R.id.etCustomDbName);
AlertDialog.Builder alert = new AlertDialog.Builder(ExistingTallyActivity.this);
/* Taken from the strings.xml file. Says Name Database Prior To Export */
alert.setMessage(getResources().getString(R.string.name_your_db));
alert.setView(view);
/* Using the global "Ok" string from strings.xml */
alert.setPositiveButton(getResources().getString(R.string.global_ok_text), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
/* Passing in the results of the editText to a string here*/
String userDefinedDbName = mEtCustomDbName.getText().toString().trim();
/*
Calling this method to rename the existing db to what the user input
Note: The original db remains in the same folder, as it was previously
backed up from the backUpDatabase() method above. Using the if statement
below to check for a empty string and if it is, the file is not renamed.
Both situations display custom toast message dependent on which executes.
Also implementing the File.separator method to help with File naming
issues on the Android "Unix-like" filesystem
*/
if (userDefinedDbName.length() > 0) {
/* Naming to a .db extension with this method. Works with SQLite */
renameDbFile(File.pathSeparator+userDefinedDbName);
/* Naming to a .csv extension with this method for working with Excel */
saveDbAsCsv(File.pathSeparator+userDefinedDbName);
Toast.makeText(ExistingTallyActivity.this,
/* Using the "Database Saved" string from strings.xml */
getResources().getString(R.string.database_saved),
Toast.LENGTH_LONG).show();
}else {
Toast.makeText(ExistingTallyActivity.this,
/* Using the "Database Not Saved" string from strings.xml */
getResources().getString(R.string.database_not_saved),
Toast.LENGTH_LONG).show();
}
}
});
/* Using the global "Cancel" string from strings.xml */
alert.setNegativeButton(getResources().getString(R.string.global_cancel_text), null);
alert.setCancelable(false);
AlertDialog showAlert = alert.create();
showAlert.show();
threadMenuSaveAndExport.start();
break;
Any advice or help would be greatly appreciated with this as I do want to be able to use the naming with / if desired as an option. Thanks

Related

How can I load and display documents from a PostGRES database via SpringBoot if the type is not given when uploading?

I have a PostGreSQL database which stores documents among other things. A user can upload any document (Pdf, Word, TFFT, Excel, ...) via a form (React). Now my question is, how can I get this document now? The document is saved as binary code in the database. So I don't know the type of document. Here's what I tried:
#PostMapping(value = "/EinzelDokument/{id}")
#CrossOrigin
public void f_pp_dokument_s(HttpServletResponse response,HttpServletRequest request, #PathVariable String id)
throws IOException, URISyntaxException {
String userEntschluesselt = entschluesselUserId(request);
String aktuellerUser = request.getParameter("aktuellerUser");
Connection con = DBVerbindung();
CallableStatement properCase = null;
ResultSet rs = null;
byte[] bild = null;
if (con != null) {
try {
con.setAutoCommit(false);
properCase = con.prepareCall("SELECT * FROM ppm.f_pp_projektdokument_s(?,?)");
properCase.setInt(1, Integer.parseInt(id));
if(aktuellerUser != null)
{
properCase.setString(2, aktuellerUser);
}
else
{
properCase.setString(2, userEntschluesselt);
}
rs = properCase.executeQuery();
con.commit();
byte[] decodedBytes = null;
if (rs.next()) {
bild = rs.getBytes("projektDokument_bin");
String splitting = new String(bild, StandardCharsets.US_ASCII);
String[] s = splitting.split(",", 2);
decodedBytes = Base64.getDecoder().decode(s[1]);
} else {
//Which document type do I have to set here, or is this approach right at all?
File file = ResourceUtils.getFile("classpath:Download.pdf");
decodedBytes = Files.readAllBytes(file.toPath());
}
response.setContentType("application/octet-stream");
response.setContentLength(decodedBytes.length);
ServletOutputStream out = response.getOutputStream();
out.write(decodedBytes, 0, decodedBytes.length);
out.flush();
out.close();
} catch (SQLException e) {
Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
logger.setLevel(Level.ALL);
logger.warning(e.getMessage());
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (con != null) {
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (properCase != null) {
try {
properCase.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
I use SpringBoot in the backend and React in the frontend.
Best case: Alter the database to add columns where you store metadata such as the kind and version of format.
Worst case: Retrieve the document, then successively decode the data into each kind of expected document. Examine the first part of the data to find expected parts, or try using utility libraries or apps to open the data as a file while trapping for exceptions/errors.

Why isn't RandomAccessFile.seek(0); moving the pointer back to the start of the file?

I'm trying to use the RandomAccessFile class to read and write information from a .json file that I pulled from a URL to an internal file for an android app, but I'm having some trouble. I've made sure that I put url.oponConnection(); in an AsyncTask so it doesn't have to run on the main activity, and I have verified that the information is being read from the .json file. (I have it output each line to my logcat).
Now my problem is that I can't read the file I created, because the pointer for the RandomAccessFile isn't being moved to the start of the file even after I've used RandomAccessFile.seek(0) I would like to make this file a .txt file if possible. I know this is a lot of code to read, but I have looked everywhere and I can't figure it out. Any help is appreciated.
AsyncTask
public class AsyncTaskActivity extends Activity {
public static class AsyncInfo extends AsyncTask<Void, Void, String>
{
protected void onPostExecute() {
}
#Override
protected void onPreExecute() {
}
#Override
protected String doInBackground(Void... params) {
try {
Log.i("AsyncTask", "Loading...");
// Make a URL to the web page
URL url = new URL("http://api.wunderground.com/api/0c0fcc3bf62ab910/conditions/q/IN/Fort_Wayne.json");
// Get the input stream through URL Connection
URLConnection con = url.openConnection();
InputStream is = con.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line;
// read each line and write to text file
while ((line = br.readLine()) != null) {
Log.i("AsyncTask", line);
TextEditor.file = new File(MainActivity.path, "siteInfo.txt");
TextEditor.writeString(line);
}
TextEditor.saveAndClose();
} catch (IOException e) {
e.printStackTrace();
}
Log.i("AsyncTask", "DONE");
return "Executed";
}
}
}
TestEditor class here is where I am trying to read and write the file
public class TextEditor {
public static File file;
private static RandomAccessFile in;
private static RandomAccessFile out;
private static String s;
/**
* Opens a file to be used for input (if not already open),
* reads a line from the file, and returns the entire line of data.
*
* #return a line of text from the input file
*/
public static String readString() {
if (in == null) {
try {
in = new RandomAccessFile(file, "rw");//new BufferedReader(new FileReader(file));
in.seek(0);
s = in.readLine();
Log.e("readString", "STRING S: " + s + ".");
return s;
} catch (Exception e) {
System.err.println("Cannot open file for input!");
e.printStackTrace();
}
}
return s;
}
/**
* Opens a file to be used for output (if not already open),
* writes a string to the file and wrties a newline.
*
* #param s The string text to be written. Follwing the string, a newline is added to the file.
*/
public static void writeString(String s) {
try {
out = new RandomAccessFile(file, "rw");
out.seek(0);
out.write(s.getBytes());
}
catch (IOException e) {
e.printStackTrace();
Log.e("writeString", "File Writer Failure");
}
}
/**
* Saves and closes the file (when opened for either input or output).
* <p/>
* Note: If the program terminates before the file is closed,
* no data will be saved or written to the file.
*/
public static void saveAndClose() {
if (in != null) {
try {
in.close();
in = null;
} catch (Exception e) {
System.err.println("Cannot close input file!");
e.printStackTrace();
}
}
if (out != null) {
try {
out.close();
out = null;
} catch (Exception e) {
System.err.println("Cannot close output file!");
e.printStackTrace();
}
}
}
This is the .json file
{
"response": {
"version":"0.1",
"termsofService":"http://www.wunderground.com/weather/api/d/terms.html",
"features": {
"conditions": 1
}
}
, "current_observation": {
"image": {
"url":"http://icons.wxug.com/graphics/wu2/logo_130x80.png",
"title":"Weather Underground",
"link":"http://www.wunderground.com"
},
"display_location": {
"full":"Fort Wayne, IN",
"city":"Fort Wayne",
"state":"IN",
"state_name":"Indiana",
"country":"US",
"country_iso3166":"US",
"zip":"46801",
"magic":"1",
"wmo":"99999",
"latitude":"41.13000107",
"longitude":"-85.12999725",
"elevation":"242.9"
},
"observation_location": {
"full":"Ludwig Park, Fort Wayne, Indiana",
"city":"Ludwig Park, Fort Wayne",
"state":"Indiana",
"country":"US",
"country_iso3166":"US",
"latitude":"41.135193",
"longitude":"-85.150581",
"elevation":"774 ft"
},
"estimated": {
},
"station_id":"KINFORTW73",
"observation_time":"Last Updated on December 14, 10:34 PM EST",
"observation_time_rfc822":"Wed, 14 Dec 2016 22:34:42 -0500",
"observation_epoch":"1481772882",
"local_time_rfc822":"Wed, 14 Dec 2016 22:34:50 -0500",
"local_epoch":"1481772890",
"local_tz_short":"EST",
"local_tz_long":"America/New_York",
"local_tz_offset":"-0500",
"weather":"Partly Cloudy",
"temperature_string":"11.3 F (-11.5 C)",
"temp_f":11.3,
"temp_c":-11.5,
"relative_humidity":"44%",
"wind_string":"From the WSW at 4.9 MPH Gusting to 7.4 MPH",
"wind_dir":"WSW",
"wind_degrees":243,
"wind_mph":4.9,
"wind_gust_mph":"7.4",
"wind_kph":7.9,
"wind_gust_kph":"11.9",
"pressure_mb":"1022",
"pressure_in":"30.17",
"pressure_trend":"+",
"dewpoint_string":"-6 F (-21 C)",
"dewpoint_f":-6,
"dewpoint_c":-21,
"heat_index_string":"NA",
"heat_index_f":"NA",
"heat_index_c":"NA",
"windchill_string":"3 F (-16 C)",
"windchill_f":"3",
"windchill_c":"-16",
"feelslike_string":"3 F (-16 C)",
"feelslike_f":"3",
"feelslike_c":"-16",
"visibility_mi":"10.0",
"visibility_km":"16.1",
"solarradiation":"0",
"UV":"0.0","precip_1hr_string":"0.00 in ( 0 mm)",
"precip_1hr_in":"0.00",
"precip_1hr_metric":" 0",
"precip_today_string":"0.00 in (0 mm)",
"precip_today_in":"0.00",
"precip_today_metric":"0",
"icon":"partlycloudy",
"icon_url":"http://icons.wxug.com/i/c/k/nt_partlycloudy.gif",
"forecast_url":"http://www.wunderground.com/US/IN/Fort_Wayne.html",
"history_url":"http://www.wunderground.com/weatherstation/WXDailyHistory.asp?ID=KINFORTW73",
"ob_url":"http://www.wunderground.com/cgi-bin/findweather/getForecast?query=41.135193,-85.150581",
"nowcast":""
}
}
So I figured out how to read/write the data as a string using a Scanner and a BufferedWriter. Here is the edited TextEditor class.
public class TextEditor {
public static File file;
private static Scanner in;
private static BufferedWriter out;
/**
* Opens a file to be used for input (if not already open),
* reads a line from the file, and returns the entire line of data.
*
* #return a line of text from the input file
*/
public static String readString() {
if (in == null) {
try {
in = new Scanner(file);
} catch (Exception e) {
System.err.println("Cannot open file for input!");
e.printStackTrace();
}
}
try {
if (in.hasNext()) {
String s = in.nextLine();
return s;
} else {
return null;
}
} catch (Exception e) {
System.err.println("Cannot read file!");
e.printStackTrace();
}
return null;
}
/**
* Opens a file to be used for output (if not already open),
* writes a string to the file and writes a newline.
*
* #param s The string text to be written. Following the string, a newline is added to the file.
*/
public static void writeString(String s) {
if (out == null) {
try {
out = new BufferedWriter(new FileWriter(file));
}
catch (Exception e) {
System.err.println("Cannot create file for output!");
e.printStackTrace();
}
}
try {
out.write(s);
out.newLine();
}
catch (Exception e) {
System.err.println("Cannot write file!");
e.printStackTrace();
}
}
/**
* Saves and closes the file (when opened for either input or output).
* <p/>
* Note: If the program terminates before the file is closed,
* no data will be saved or written to the file.
*/
public static void saveAndClose() {
if (in != null) {
try {
in.close();
in = null;
}
catch (Exception e) {
System.err.println("Cannot close input file!");
e.printStackTrace();
}
}
if (out != null) {
try {
out.close();
out = null;
}
catch (Exception e) {
System.err.println("Cannot close output file!");
e.printStackTrace();
}
}
}
}

save a created propertyfile in specific folder

How can I save a prop file in a specific folder for example,
now it is saved in the root I guess, but it needs to be in the same folder as the class where it is created.
I also want to know how to load it. If it possible to load a properties file easily from the root then it is okay as well to save it in the root.
code creating the file, first 2 lines with // ( = make code work now without using prop file), class name = Providers
public static DataAccessProvider createProvider (URL url) {
//MovieDAOOnline mdaoOn = new MovieDAOOnline();
//mdaoOn.setUrl(url);
Properties prop = new Properties();
OutputStream output = null;
try {
output = new FileOutputStream("config.properties");
// set the properties value
prop.setProperty("uri", url.toString());
prop.store(output, null);
} catch (IOException io) {
io.printStackTrace();
} finally {
if (output != null) {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return new OnlineProvider();
}
code for getting the file, first line in comment needs to be changed to get uri from propertie:
public Movie getMovie(int id) throws DataAccessException{
//StringBuilder builder = new StringBuilder(url.toString());
builder.append("movies.xml");
MovieConfigRead mcr = new MovieConfigRead();
List<Movie> film = null;
try {
film = mcr.geefMovies(builder.toString());
} catch (JAXBException e) {
throw new DataAccessException();
} catch (MalformedURLException e) {
throw new DataAccessException();
}
for (Movie movie : film) {
if (movie.getId() == id) {
return movie;
}
}
return null;
}

Android Database Not Always Getting Deleted On Uninstall/Install

when i try to uninstall my android app and reinstall it again to get the new updated database, the database sometimes does not get updated, i don't know why.
Database gets updated after trying a random number of attempts of install/uninstall,
Can someone help me with this problem.
What I tried is:
when uninstalling, first I force stop the application, then I cleared the data and then uninstalled.
here is the code that is executed in the MainActivity when the app starts.
try {
File dbFile = getDatabasePath("MyDatabase.db");
if (!dbFile.exists()) {
Log.d(TAG, "Datbase does not exist");
this.copy("MY.db",dbFile.getAbsolutePath());
}
}
catch (Exception e) {
Log.e(TAG, "Error in Copying: "+e.toString());
try {
AppLogging(TAG, "Error in copying Database:" + e.toString());
}
catch(Exception l) {
}
}
Copy method
private void copy(String file, String folder) throws IOException {
try {
File CheckDirectory;
CheckDirectory = new File(folder);
String parentPath = CheckDirectory.getParent();
File filedir = new File(parentPath);
if (!filedir.exists()) {
if (!filedir.mkdirs()) {
return;
}
}
InputStream in = this.getApplicationContext().getAssets().open(file);
File newfile = new File(folder);
OutputStream out = new FileOutputStream(newfile);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
catch (Exception e) {
Log.e(TAG, "Error in Copy: "+e.toString());
try {
AppLogging(TAG, "ERROR In Copy Method (Database) " + e.toString());
}
catch(Exception l) {
}
}
}

Java - passing input into external C/C++ application

I'm trying to enter some value in external application using Java.
Java application looks like this:
Runtime runtime = Runtime.getRuntime();
// ... str build ...
proc = runtime.exec(str);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
bw.write(value);
bw.flush();
bw.close();
if (proc.waitFor() != 0)
// error msg
// the end
Application hangs at waitFor method.
External application looks like this:
welcome banner
please enter 8 character input:
Welcome banner is printed using printf and input is taken with SetConsoleMode/ReadConsoleInput. ReadConsoleInput reads one char and they are masked with * character.
Help
you can use:
proc.getOutputStream().write("some date".getBytes())
keep in mind that you HAVE to read everything the app send to stdout and stderr, else it might get stuck writing there.
I use a generic class to read it in a different thread.
usage is like:
InputStreamSucker inSucker = new InputStreamSucker(proc.getInputStream());
InputStreamSucker errSucker = new InputStreamSucker(proc.getErrorStream());
proc.waitFor();
int exit = process.exitValue();
inSucker.join();
errSucker.join();
InputStreamSucker code is here:
public class InputStreamSucker extends Thread
{
static Logger logger = Logger.getLogger(InputStreamSucker.class);
private final BufferedInputStream m_in;
private final ByteArrayOutputStream m_out;
private final File m_outFile;
public InputStreamSucker(InputStream in) throws FileNotFoundException
{
this(in, null);
}
public InputStreamSucker(InputStream in, File outFile) throws FileNotFoundException
{
m_in = new BufferedInputStream(in, 4096);
m_outFile = outFile;
m_out = new ByteArrayOutputStream();
start();
}
#Override
public void run()
{
try
{
int c;
while ((c = m_in.read()) != -1)
{
m_out.write(c);
}
}
catch (IOException e)
{
logger.error("Error pumping stream", e);
}
finally
{
if (m_in != null)
{
try
{
m_in.close();
}
catch (IOException e)
{
}
}
try
{
m_out.close();
}
catch (IOException e)
{
logger.error("Error closing out stream", e);
}
if (m_outFile != null)
{
byte data[] = m_out.toByteArray();
if (data.length > 0)
{
FileOutputStream fo = null;
try
{
fo = new FileOutputStream(m_outFile);
fo.write(data);
}
catch (IOException e)
{
logger.error("Error writing " + m_outFile);
}
finally
{
try
{
if (fo != null) fo.close();
}
catch (IOException e)
{
logger.error("Error closing " + m_outFile);
}
}
}
}
}
}
public String getOutput()
{
return new String(m_out.toByteArray());
}
}
Got the answer! The trick is to use WriteConsoleInput() API because program expects keyboard event, not text ... That's why the waitFor() waited forever! :)

Categories