If I use the File.getText() method in groovy
newFile().text or newFile().getText()
do I have to execute some closure statements to close the used file reader or will the method do it by itself?
It will do it by itself.
Calling new File( 'a.txt' ).text will call ResourceGroovyMethods.getText( File )
public static String getText(File file, String charset) throws IOException {
return IOGroovyMethods.getText(newReader(file, charset));
}
Which as you can see calls IOGroovyMethods.getText( BufferedReader ):
public static String getText(BufferedReader reader) throws IOException {
StringBuilder answer = new StringBuilder();
// reading the content of the file within a char buffer
// allow to keep the correct line endings
char[] charBuffer = new char[8192];
int nbCharRead /* = 0*/;
try {
while ((nbCharRead = reader.read(charBuffer)) != -1) {
// appends buffer
answer.append(charBuffer, 0, nbCharRead);
}
Reader temp = reader;
reader = null;
temp.close();
} finally {
closeWithWarning(reader);
}
return answer.toString();
}
Which as you can see, closes the Reader when done
Related
This is my first app on Android with Java and SQLite.
ISSUE:
I have a local SQLIte db on my app. I was very surprised to see how easy it is to get access to the db once you have installed the app (no need to be a programmer nor a hacker).
I tried adding SQLCipher to my app but it only worked for newer Android versions 11 & 12 and didn't work for Android 9 for example and it did make my app's size much bigger.
After researching more I found a better solution for my case which doesn"t involve crypting the db with SQLCipher but rather it consists of corrupting the first bytes of the db file then after each launch of the app the code will decorrupt the file and use the fixed file instead. This insures that anyone who decompiles the apk will only get access to a corrupt db file and will have to put more effort to fix it which is my goal.
I came across this solution in a reply [here][1] but I don't know how to implement it as I am new to Android and SQLite programming. Any help is much appreciated on how to actually do it.
These are the steps as mentioned by the user: farhad.kargaran which need more explanation as I don't get how to do it:
1- corrupt the db file (convert it to byte array and change some values)
2- copy it in asset folder
3- in first run fix corrupted file from asset and copy it in database
folder.
Change first 200 byte values like this:
int index = 0;
for(int i=0;i<100;i++)
{
byte tmp = b[index];
b[index] = b[index + 1];
b[index + 1] = tmp;
index += 2;
}
As only the first 200 bytes were replaced, the same code is used for fixing first 200 byte values.
Here is my code for the SQLiteOpenHelper if needed:
public class DatabaseHelper extends SQLiteOpenHelper {
private static final String TAG = DatabaseHelper.class.getSimpleName();
public static String DB_PATH;
public static String DB_NAME;
public SQLiteDatabase database;
public final Context context;
public SQLiteDatabase getDb() {
return database;
}
public DatabaseHelper(Context context, String databaseName, int db_version) {
super(context, databaseName, null, db_version);
this.context = context;
DB_PATH = getReadableDatabase().getPath();
DB_NAME = databaseName;
openDataBase();
// prepare if need to upgrade
int cur_version = database.getVersion();
if (cur_version == 0) database.setVersion(1);
Log.d(TAG, "DB version : " + db_version);
if (cur_version < db_version) {
try {
copyDataBase();
Log.d(TAG, "Upgrade DB from v." + cur_version + " to v." + db_version);
database.setVersion(db_version);
} catch (IOException e) {
Log.d(TAG, "Upgrade error");
throw new Error("Error upgrade database!");
}
}
}
public void createDataBase() {
boolean dbExist = checkDataBase();
if (!dbExist) {
this.getReadableDatabase();
this.close();
try {
copyDataBase();
} catch (IOException e) {
Log.e(TAG, "Copying error");
throw new Error("Error copying database!");
}
} else {
Log.i(this.getClass().toString(), "Database already exists");
}
}
private boolean checkDataBase() {
SQLiteDatabase checkDb = null;
try {
String path = DB_PATH + DB_NAME;
checkDb = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY);
} catch (SQLException e) {
Log.e(TAG, "Error while checking db");
}
if (checkDb != null) {
checkDb.close();
}
return checkDb != null;
}
private void copyDataBase() throws IOException {
InputStream externalDbStream = context.getAssets().open(DB_NAME);
String outFileName = DB_PATH + DB_NAME;
OutputStream localDbStream = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = externalDbStream.read(buffer)) > 0) {
localDbStream.write(buffer, 0, bytesRead);
}
localDbStream.close();
externalDbStream.close();
}
public SQLiteDatabase openDataBase() throws SQLException {
String path = DB_PATH + DB_NAME;
if (database == null) {
createDataBase();
database = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READWRITE);
}
return database;
}
#Override
public synchronized void close() {
if (database != null) {
database.close();
}
super.close();
}
Much appreciated.
[1]: https://stackoverflow.com/a/63637685/18684673
As part of the copyDatabase, correct and then write the corrupted data, then copy the rest.
Could be done various ways
e.g.
long buffersRead = 0; //<<<<< ADDED for detecting first buffer
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = externalDbStream.read(buffer)) > 0) {
if (bufferesRead++ < 1) {
//correct the first 200 bytes here before writing ....
}
localDbStream.write(buffer, 0, bytesRead);
}
I have an app with data files (some images and xml files) i have packed them up in a zip file.
I open the file with zipme and save the files. I used this code for that
private void save1( ) {
InputStream is;
FileChooser.showOpenDialog(".zip", new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (e != null && e.getSource() != null) {
String file = (String)e.getSource();
FileSystemStorage fs = FileSystemStorage.getInstance();
try {
InputStream is = fs.openInputStream(file);
ZipInputStream zipStream = new ZipInputStream(is);
ZipEntry entry;
// create a buffer to improve copy performance later.
byte[] buffer = new byte[2048];
while ((entry = zipStream.getNextEntry()) != null) {
String s = entry.getName();
String outdir = FileSystemStorage.getInstance().getAppHomePath();
if (outdir.length() > 0) {
outdir = outdir ;
}
String outpath = outdir + "/" + entry.getName();
OutputStream output = null;
try {
output = FileSystemStorage.getInstance().openOutputStream(outpath);
int len = 0;
while ((len = zipStream.read(buffer)) > 0) {
output.write(buffer, 0, len);
}
} finally {
// we must always close the output file
if (output != null) {
output.close();
}
}
} } catch (IOException ex) {
Log.p(ex.getMessage(), 0); } } }});}
i see in netbeans that in the simulator the files are saved to
users/.cn1
So this works on the desktop
To fetch the image i use
String outdir = FileSystemStorage.getInstance().getAppHomePath();
Image uur1 = EncodedImage.create(outdir + "/West.jpg");
i also tried without outdir but also no luck.
What do i wrong.
This should work without the extra slash:
Image uur1 = EncodedImage.create(outdir + "West.jpg");.
Notice that this code is case sensitive so make sure the file has the right casing. Is this failing on the simulator, if so place a breakpoint on the loading code and make sure the file is physically there
The answer i found on my question is:
1 No extra slash as Shai Among suggested:
2 Make a inputstream for enecodedimage.create() instead of only a string with the path to the file
Without the second part the app doesn't run correctly in the simulation and on the device
FileSystemStorage fs = FileSystemStorage.getInstance();
String outdir = FileSystemStorage.getInstance().getAppHomePath();
String outpath = outdir + West.jpg;
InputStream isk = fs.openInputStream(outpath);
Image uur = EncodedImage.create(isk);
I have a problem with C# read(){} function. When I open and read my document it does not read the first line:
private static void read(string file, Konteineris butas)
{
using (StreamReader reader = new StreamReader(#file))
{
string line;
line = reader.ReadLine();
while (null != (line = reader.ReadLine()))
{
string[] values = line.Split(';');
int nr = Convert.ToInt16(values[0]);
double plotas = Convert.ToDouble(values[1]);
int kambariusk = Convert.ToInt16(values[2]);
int kaina = Convert.ToInt32(values[3]);
string tnr = values[4];
Apartaments apart = new Butas(nr,plotas,kambariusk,kaina,tnr); // array of apartaments
apartaments.addapartament(apart);
}
}
}
the text file:
1;25,4;1;25000;867467212 // skips this line...
2;26,4;2;100000;867467212
3;75,4;3;2100;867467212
4;65,4;4;15000;867467212
Remove the first call to line = reader.ReadLine(); You are calling ReadLine() your loop, so you don't need it there.
Because you do a line = reader.ReadLine(); then follow it up with the same code in the while loop, by the time it hits it's first iteration of the loop, it's already done a .ReadLine() twice, thus is on the second line of the file.
Remove the line = reader.ReadLine(); from the code and retry.
private static void read(string file, Konteineris butas)
{
using (StreamReader reader = new StreamReader(#file))
{
string line;
line = reader.ReadLine();
while (null != (line = reader.ReadLine()))
{
string[] values = line.Split(';');
int nr = Convert.ToInt16(values[0]);
double plotas = Convert.ToDouble(values[1]);
int kambariusk = Convert.ToInt16(values[2]);
int kaina = Convert.ToInt32(values[3]);
string tnr = values[4];
Apartaments apart = new Apartaments(nr,plotas,kambariusk,kaina,tnr); // array of apartaments
apartaments.addapartament(apart);
}
}
}
remove this. since your while condition does this already and you will jump over the first line based on this call.
line = reader.ReadLine(); gives you a new line every time you call it.
So in your while condition you get your second line without using your first.
way1:
private static void read(string file, Konteineris butas)
{
using (StreamReader reader = new StreamReader(#file))
{
string line;
while (null != (line = reader.ReadLine()))
{
string[] values = line.Split(';');
int nr = Convert.ToInt16(values[0]);
double plotas = Convert.ToDouble(values[1]);
int kambariusk = Convert.ToInt16(values[2]);
int kaina = Convert.ToInt32(values[3]);
string tnr = values[4];
Apartaments apart = new Apartaments(nr,plotas,kambariusk,kaina,tnr); // array of apartaments
apartaments.addapartament(apart);
}
}
}
way2:
private static void read(string file, Konteineris butas)
{
using (StreamReader reader = new StreamReader(#file))
{
string line;
while (line!=null)
{
line = reader.ReadLine();
string[] values = line.Split(';');
int nr = Convert.ToInt16(values[0]);
double plotas = Convert.ToDouble(values[1]);
int kambariusk = Convert.ToInt16(values[2]);
int kaina = Convert.ToInt32(values[3]);
string tnr = values[4];
Apartaments apart = new Apartaments(nr,plotas,kambariusk,kaina,tnr); // array of apartaments
apartaments.addapartament(apart);
}
}
}
I want to use the class IpAddress instead of String in my List, like this:
ArrayList<IpAddress> IpAddresses = new ArrayList<>();
But it doesn't work. I cannot add the string line to my list, so the program does not work as I want. What should I do?
public class IpAddress implements Comparable<IpAddress> {
private String ip;
public IpAddress(String ip) {
this.ip = ip;
}
#Override
public int compareTo(IpAddress o) {
return this.ip.compareTo(o.ip);
}
}
public class IPvLIST {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader(new File("ip.txt"));
BufferedReader br = new BufferedReader(fr);
ArrayList<String> IpAddresses = new ArrayList<>();
String line;
int n = 0;
while ((line = br.readLine()) != null) {
IpAddresses.add(line);
}
}
}
You need to convert the string line to an IpAddress. Based on the code you have, change the while statement to
while ((line = br.readLine()) != null) {
IpAddresses.add(new IpAddress(line));
}
Depending if this is a simple test program or something more, you might also look into the .NET class IPAddress. This has a parse function that will take the string and convert it to an IPAddress which makes it easier to perform actual network functions.
I tried the example from "J2ME/Blackberry - how to read/write text file?". I want only the read functionality, the file I want to read is in CSV format as a .txt file placed in the /res/test.txt.
But I am having an issue with the FileConnection. I get the following error:
File system error (1003)
Any suggestions or advice on a better approach or as to how I can get this working?
public class FileDemo extends MainScreen {
public FileDemo() {
setTitle("My Page");
String str = readTextFile("file:///test.txt");
System.out.println("Contents of the file::::::: " + str);
}
public String readTextFile(String fName) {
String result = null;
FileConnection fconn = null;
DataInputStream is = null;
try {
fconn = (FileConnection) Connector.openInputStream(fName);
is = fconn.openDataInputStream();
byte[] data = IOUtilities.streamToBytes(is);
result = new String(data);
} catch (IOException e) {
System.out.println(e.getMessage());
} finally {
try {
if (null != is)
is.close();
if (null != fconn)
fconn.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
return result;
}
}
try this
InputStream is = getClass().getResourceAsStream("/test.txt");
StringBuffer buff = new StringBuffer();
int ch;
try {
while ((ch = is.read()) != -1)
buff.append((char) ch);
} catch (Exception e) {
Log.Error(e, "Exception ");
}
String str = (buff.toString());
Same problem I also faced in my project. First check your simulator memory card is inserted or not. From simulator,
go to Options(Settings)-->Device-->Storage and Check the Memory card Storage.
If the memory card is not inserted, than it will show Media Card is not currently inserted in the device. So, you need to insert the memory card. From simulator menu bar, choose simulate-->Change SD Card...
You can add the SD card here. Than you try.
I think, This suggestion will help someone.