I have created a game in Android. I have written a class for input/ouput with prefer install location external. I want to make some basic questions. First of all the file I use is a .txt (I know that its not the best way to save your data but I use it for testing). The strange part is that when the the game is over it should automatically save the user highscores but it does not, so when I close the app and restart it the highscores have disappeared. I would also like to learn what the prefered file type for saving settings/highscores/coins etc (hopefully secured) is. Lastly I debug the game using a Nexus 5 whitch does not have external storage (it should be stored locally though). This is my code, thanks in advance :).
public class AndroidFileIO implements FileIO {
Context context;
AssetManager assets;
String externalStoragePath;
public AndroidFileIO(Context context) {
this.context = context;
this.assets = context.getAssets();
this.externalStoragePath = Environment.getExternalStorageDirectory()
.getAbsolutePath() + File.separator;
}
public InputStream readAsset(String fileName) throws IOException {
return assets.open(fileName);
}
public InputStream readFile(String fileName) throws IOException {
return new FileInputStream(externalStoragePath + fileName);
}
public OutputStream writeFile(String fileName) throws IOException {
return new FileOutputStream(externalStoragePath + fileName);
}
public SharedPreferences getPreferences() {
return PreferenceManager.getDefaultSharedPreferences(context);
}
}
my game class has this method
public FileIO getFileIO() {
return fileIO;
}
this is the way i load the file
Settings.load(game.getFileIO());
and finaly my save/load methods of the settings class
public static void load(FileIO files) {
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(
files.readFile("mrnom.txt")));
soundEnabled = Boolean.parseBoolean(in.readLine());
for (int i = 0; i < 5; i++) {
highscores[i] = Integer.parseInt(in.readLine());
}
} catch (IOException e) {
// :( It's ok we have defaults
} catch (NumberFormatException e) {
// :/ It's ok, defaults save our day
} finally {
try {
if (in != null)
in.close();
} catch (IOException e) {
}
}
}
public static void save(FileIO files) {
BufferedWriter out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(
files.writeFile("mrnom.txt")));
out.write(Boolean.toString(soundEnabled));
for (int i = 0; i < 5; i++) {
out.write(Integer.toString(highscores[i]));
}
} catch (IOException e) {
} finally {
try {
if (out != null)
out.close();
} catch (IOException e) {
}
}
}
Here save is called
private void updateGameOver(List<TouchEvent> touchEvents) {
int len = touchEvents.size();
for(int i = 0; i < len; i++) {
TouchEvent event = touchEvents.get(i);
if(event.type == TouchEvent.TOUCH_UP) {
if(event.x >= 128 && event.x <= 192 &&
event.y >= 200 && event.y <= 264) {
if(Settings.soundEnabled)
Assets.click.play(1);
//debug begin
FileIO fileIO = game.getFileIO();
Settings.save(fileIO);
//debug end
game.setScreen(new MainMenuScreen(game));
return;
}
}
}
}
Your issue is in the save method when you write the strings to the out reference. You are not saving a value per line, but are later reading a value per line in your load method. With the current code you save the following in your mrnom.txt file: true10203040 instead of true\n10\n20\n30\n40.
To fix this, one way is to change:
out.write(Boolean.toString(soundEnabled));
to
out.write(Boolean.toString(soundEnabled) + "\n");
AND
out.write(Integer.toString(highscores[i]));
to
out.write(Integer.toString(highscores[i]) + "\n");
Related
I this is my java HTTP server:
public class WebServer implements Runnable {
public static final int PORT = 80;
#Override
public void run() {
HttpServer $server;
try {
$server = HttpServer.create(new InetSocketAddress(80), 0);
} catch (IOException _e) {
throw new RuntimeException(_e);
}
$server.createContext("/", _httpExchange ->
{
String $uri = _httpExchange.getRequestURI().toString();
$uri = $uri.startsWith("/") ? $uri.replaceFirst("/", "") : $uri;
if ($uri.equals("")) {
sendFile("test.html", _httpExchange);
}
else if ($uri.matches(".*\\.[^/.]+")) {
sendFile($uri, _httpExchange);
}
else {
sendFile($uri + ".html", _httpExchange);
}
});
$server.start();
System.out.println("Server started at " + getPrivateIp() + " on port " + PORT);
}
private static String getPrivateIp() {
try (final DatagramSocket datagramSocket = new DatagramSocket()) {
datagramSocket.connect(InetAddress.getByName("8.8.8.8"), 12345);
return datagramSocket.getLocalAddress().getHostAddress();
} catch (UnknownHostException | SocketException _e) {
throw new RuntimeException(_e);
}
}
public static void sendFile(String _name, HttpExchange _exchange) throws IOException {
try {
InputStream $stream = WebServer.class.getResourceAsStream(_name);
if ($stream == null) {
_exchange.sendResponseHeaders(404, 0);
_exchange.close();
return;
}
Scanner $scanner = new Scanner($stream).useDelimiter("\\A");
String $response = $scanner.next();
_exchange.getResponseBody();
_exchange.sendResponseHeaders(200, $response.getBytes().length);
_exchange.getResponseBody().write($response.getBytes());
_exchange.close();
} catch (Exception _ex) {
throw new RuntimeException(_ex);
}
}
}
When I run it, and then open my website, everything is ok, but I cannot see any images. In the network tab, it says that the image was accepted, but it's not shown. I tried using Files.copy() in sendFile() method, but it didn't work - it didn't show the website, nor the image! (Not even when I did localhost/image.jpg).
In the network tab, it also shows that the MIME type is img/jpeg, which is correct, so it's not because of that...
Using wget, I get a normal looking .jpg file, but if I open it, it's corrupted...
Does someone know how to fix this?
Thanks.
Solved it!
You just check if the request wants .png or .jpg file (or you can just check the MIME type), and if it does, then you have to use ImageIO class
public static void sendFile(String _name, HttpExchange _exchange) {
try {
InputStream $stream = WebServer.class.getResourceAsStream(_name);
if ($stream == null) {
_exchange.sendResponseHeaders(404, 0);
_exchange.close();
return;
}
if (_name.matches(".*?\\.(png|PNG|jpg|JPG|jpeg|JPEG)")) {
BufferedImage $image = ImageIO.read($stream);
if (_name.toLowerCase().endsWith("png")) {
_exchange.sendResponseHeaders(200, getImageSize($image, "png"));
ImageIO.write($image, "png", _exchange.getResponseBody());
}
else {
_exchange.sendResponseHeaders(200, getImageSize($image,"jpeg"));
ImageIO.write($image, "jpeg", _exchange.getResponseBody());
}
$stream.close();
_exchange.close();
return;
}
Scanner $scanner = new Scanner($stream).useDelimiter("$");
String $response = $scanner.next();
_exchange.getResponseBody();
_exchange.sendResponseHeaders(200, $response.length());
_exchange.getResponseBody().write($response.getBytes());
_exchange.close();
} catch (Exception _ex) {
throw new RuntimeException(_ex);
}
}
I'm using the following code to search specific files in my computer and write the absolute path in a text file. My problem is that every time I run this code it add duplicate lines into text file, i want to add only those lines(file path) which are not written in the text file at that time (no duplicates).. Thank you
public static void walkin(File dir) {
String pattern = ".mp4";
try {
PrintWriter out = new PrintWriter(new BufferedWriter(
new FileWriter("D:\\nawaaaaaa.txt", true)));
File listFile[] = dir.listFiles();
if (listFile != null) {
for (int i = 0; i < listFile.length; i++) {
if (listFile[i].isDirectory()) {
walkin(listFile[i]);
} else if (listFile[i].getName().endsWith(pattern)
&& listFile[i].isFile()) {
System.out.println(listFile[i].getPath());
out.write(listFile[i].toString());
out.write("\r\n");
// out.close();
} else {
walkin(listFile[i]);
}
}
}
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Your code works for me, no idea what is the problem on your side, how you are calling it; but you can optimize your code a bit, something as follows (just very quick code, code be made nicer, but to give you an idea):
public class SomeTest {
private static HashSet<String> filez = new HashSet<String> ();
public static void walkin(File dir, PrintWriter out) {
String pattern = ".mp4";
File listFile[] = dir.listFiles();
if (listFile != null) {
for (int i = 0; i < listFile.length; i++) {
if (listFile[i].getName().endsWith(pattern) && listFile[i].isFile()) {
//System.out.println(listFile[i].getPath());
if (filez.add(listFile[i].getPath())) {
out.write(listFile[i].toString());
out.write("\r\n");
}
} else {
walkin(listFile[i], out);
}
}
}
}
public static void main(String[] args) {
try {
File dir = new File("C:\\mydir");
PrintWriter out = new PrintWriter(new BufferedWriter(
new FileWriter("D:\\nawaaaaaa.txt", true)));
walkin(dir, out);
out.close();
} catch (IOException e) {
//
}
}
}
You can use the filez hashset to print stuff, or write your file at the end of the parsing process as well.. your choice.
If you don't want duplicates in the file, you will need to keep track of the file names you have already written. A HashSet<String> is going for this. But I'm surprised the above code works at all given that you keep opening the file at the top of walkin() and walkin() itself is recursive. You need to rethink your code a bit. Possibly passing the PrintWriter into walkin() as a parameter.
Since you are running the code multiple times ("every time I run this code it add duplicate lines into text file"), so once you finish writing to the file, you read each line and store it in a HashSet<String>. And use another writer to write it to the file.
BufferedWriter writer = new BufferedWriter(new FileWriter("filename"));
for (String eachUniqueLine: `Your hash set`) {
writer.write(eachUniqueLine);
writer.newLine();
}
(It is costly as in you have to do more i/o operation)
You need to expand your method into a class that perform this kind of tasks.
You have two main problem you open a writer for each directory and you call the walkin, for things that do not apply to your logic (and open writer again).
You should try to design a class that will be able to create an index for you.
public static void main(String[] args) throws IOException {
File createTempFile = File.createTempFile("mp4", ".idx");
FileIndexer fi = new FileIndexer(createTempFile.getAbsolutePath());
fi.index("C:\\", "mp4");
System.out.println(createTempFile);
}
public static class FileIndexer {
private static final String END_OF_LINE = "\r\n";
private final String outputPath;
private final Set<String> index = new HashSet<String>();
public FileIndexer(String outputPath) {
this.outputPath = outputPath;
}
private boolean isValidPath(String path) {
return outputPath != null && outputPath.trim().length() > 0;
}
private boolean isValidIndexFile(File file) {
return file.isFile() && file.canRead() && file.canWrite();
}
private void createIndexFile(File file) throws IOException {
if(file.createNewFile() == false) {
throw new IOException("Could not create index file");
}
this.index.clear();
}
private void readIndexFile(File file) throws IOException {
isValidIndexFile(file);
index.clear();
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader(new FileReader(file));
String line;
while((line = bufferedReader.readLine()) != null) {
addToIndex(line);
}
} finally {
if(bufferedReader != null) {
bufferedReader.close();
}
}
}
private void addToIndex(String line) {
index.add(line);
}
private PrintWriter openIndex() throws IOException {
if(isValidPath(outputPath) == false) {
throw new IOException(String.format("The outputPath is not valid: [%s]",outputPath));
}
File indexFile = new File(outputPath);
if(indexFile.exists()) {
readIndexFile(indexFile);
} else {
createIndexFile(indexFile);
}
return new PrintWriter(new BufferedWriter(new FileWriter(this.outputPath, true)));
}
public synchronized void index(String pathToIndex, String pattern) throws IOException {
isValidPath(pathToIndex);
PrintWriter out = openIndex();
try {
File elementToIndex = new File(pathToIndex);
index(elementToIndex,pathToIndex, out);
} finally {
if(out != null) {
out.close();
}
}
}
private void index(File elementToIndex, String pattern, PrintWriter out) {
if(elementToIndex == null) {
return;
}
if(elementToIndex.isDirectory()) {
for(File file : elementToIndex.listFiles()) {
index(file,pattern, out);
}
}
if(elementToIndex.isFile() && elementToIndex.getAbsolutePath().endsWith(pattern)) {
writeToIndex(elementToIndex, out);
}
}
private void writeToIndex(File elementToIndex, PrintWriter out) {
out.write(elementToIndex.getAbsolutePath());
out.write(END_OF_LINE);
}
}
Problem Solved (BTW i'm not sure if it is most efficient solution or not ).......
public static void main(String[] args) {
try {
File dir = new File("D:\\To Do");
BufferedWriter out = new BufferedWriter(new FileWriter(
"D:\\path.txt", true));
walkin(dir, out);
out.close();
readfile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} // Replace this with a suitable directory
// walkin(new File("D:/to Do"));
}
public static void walkin(File dir, BufferedWriter out) throws IOException {
String pattern = ".mp4";
// BufferedWriter out = new BufferedWriter(
// new FileWriter("D:\\path.txt",true));
File listFile[] = dir.listFiles();
if (listFile != null) {
for (int i = 0; i < listFile.length; i++) {
if (listFile[i].getName().endsWith(pattern)
&& listFile[i].isFile()) {
if (filez.add(listFile[i].getPath())) {
// System.out.println(listFile[i].getPath());
out.write(listFile[i].toString());
out.write("\r\n");
// System.out.println(filez);
}
} else {
walkin(listFile[i], out);
}
}
}
}
public static void readfile() {
BufferedReader br = null;
String str;
try {
BufferedWriter out = new BufferedWriter(new FileWriter(
"D:\\duplicate_free.txt"));
br = new BufferedReader(new FileReader("D:\\path.txt"));
while ((str = br.readLine()) != null) {
if (files.contains(str)) {
} else {
files.add(str);
}
}
for (String uniq : files) {
out.write(uniq);
System.out.println(uniq);
}
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I am trying to copy folders and files which is working fine but I need help on how to filter a single folder and copy the rest of the folders. For example, I have directories like carsfolder and truckfolder in(C:\vehicle\carsfolder and C:\vehicle\truckfolder). When I use the below code it copies both carsfolder and truckfolder but I wanted to copy only carsfolder. How can I do that. Your help is highly appreciated.(Using Swing and Java 1.6)
class CopyTask extends SwingWorker<Void, Integer>
{
private File source;
private File target;
private long totalBytes = 0;
private long copiedBytes = 0;
public CopyTask(File src, File dest)
{
this.source = src;
this.target = dest;
progressAll.setValue(0);
}
#Override
public Void doInBackground() throws Exception
{
ta.append("Retrieving info ... "); //append to TextArea
retrieveTotalBytes(source);
ta.append("Done!\n");
copyFiles(source, target);
return null;
}
#Override
public void process(List<Integer> chunks)
{
for(int i : chunks)
{
}
}
#Override
public void done()
{
setProgress(100);
}
private void retrieveTotalBytes(File sourceFile)
{
try
{
File[] files = sourceFile.listFiles();
for(File file : files)
{
if(file.isDirectory()) retrieveTotalBytes(file);
else totalBytes += file.length();
}
}
catch(Exception ee)
{
}
}
private void copyFiles(File sourceFile, File targetFile) throws IOException
{
if(sourceFile.isDirectory())
{
try{
if(!targetFile.exists()) targetFile.mkdirs();
String[] filePaths = sourceFile.list();
for(String filePath : filePaths)
{
File srcFile = new File(sourceFile, filePath);
File destFile = new File(targetFile, filePath);
copyFiles(srcFile, destFile);
}
}
catch(Exception ie)
{
}
}
else
{
try
{
ta.append("Copying " + sourceFile.getAbsolutePath() + " to " + targetFile.getAbsolutePath() );
bis = new BufferedInputStream(new FileInputStream(sourceFile));
bos = new BufferedOutputStream(new FileOutputStream(targetFile));
long fileBytes = sourceFile.length();
long soFar = 0;
int theByte;
while((theByte = bis.read()) != -1)
{
bos.write(theByte);
setProgress((int) (copiedBytes++ * 100 / totalBytes));
publish((int) (soFar++ * 100 / fileBytes));
}
bis.close();
bos.close();
publish(100);
ta.append(" Done!\n");
}
catch(Exception excep)
{
setProgress(0);
bos.flush();
bis.close();
bos.close();
}
finally{
try {
bos.flush();
}
catch (Exception e) {
}
try {
bis.close();
}
catch (Exception e) {
}
try {
bos.close();
}
catch (Exception e) {
}
}
}
}
}
Maybe you can introduce a regex or list of regexes that specify which files and dirs to exclude?
For example, to exclude truckfolder, use a "exclusion" regex like "C:\\vehicle\\truckfolder.*".
Then, in your code, before you copy anything, check to make sure the absolute path of the sourcefile doesn't match the exclusion regex(s).
I am trying to copy files from windows server1 to another windows server2 and not sure where to put the try catch block. I want to inform the user whenver windows server1 or windows server2 shuts down while copying process is ongoing either throught a popup or displaying in a textArea and here is my swingworker code. Thanks in advance
class CopyTask extends SwingWorker<Void, Integer>
{
private File source;
private File target;
private long totalBytes = 0;
private long copiedBytes = 0;
public CopyTask(File src, File dest)
{
this.source = src;
this.target = dest;
progressAll.setValue(0);
progressCurrent.setValue(0);
}
#Override
public Void doInBackground() throws Exception
{
ta.append("Retrieving info ... ");
retrieveTotalBytes(source);
ta.append("Done!\n");
copyFiles(source, target);
return null;
}
#Override
public void process(List<Integer> chunks)
{
for(int i : chunks)
{
progressCurrent.setValue(i);
}
}
#Override
public void done()
{
setProgress(100);
}
private void retrieveTotalBytes(File sourceFile)
{
File[] files = sourceFile.listFiles();
for(File file : files)
{
if(file.isDirectory()) retrieveTotalBytes(file);
else totalBytes += file.length();
}
}
private void copyFiles(File sourceFile, File targetFile) throws IOException
{
if(sourceFile.isDirectory())
{
if(!targetFile.exists()) targetFile.mkdirs();
String[] filePaths = sourceFile.list();
for(String filePath : filePaths)
{
File srcFile = new File(sourceFile, filePath);
File destFile = new File(targetFile, filePath);
copyFiles(srcFile, destFile);
}
}
else
{
ta.append("Copying " + sourceFile.getAbsolutePath() + " to " + targetFile.getAbsolutePath() ); //appends to textarea
bis = new BufferedInputStream(new FileInputStream(sourceFile));
bos = new BufferedOutputStream(new FileOutputStream(targetFile));
long fileBytes = sourceFile.length();
long soFar = 0;
int theByte;
while((theByte = bis.read()) != -1)
{
bos.write(theByte);
setProgress((int) (copiedBytes++ * 100 / totalBytes));
publish((int) (soFar++ * 100 / fileBytes));
}
bis.close();
bos.close();
publish(100);
}
}
Where is the line where the exception can happen? That's the first place I locate any exception.
Generally, if your modules are small, you can wrap the try around all the real code in the module and catch the exceptions at the end, especially if the exception is fatal. Then you can log the exception and return an error message/status to the user.
However, the strategy is different if the exception is not fatal. In this case you'll have to handle it right where the connection exception is thrown so you can seamlessly resume when the connection returns. Of course, this is a little more work.
EDIT - you probably want bis.close() and bos.close() inside a finally block to ensure they get closed. It may be pedantic but it seems prudent.
1.Problem on emulator:
I am launching my midlet app at first time is to store some data and then I am restarting it at second time is to read the stored data. It is working well in first two cases without any exception.
However I am restarting it second time on the same way then It gives exception: "Uncaught exception java/lang/NumberFormatException:" it is processing only char and total data is less than 64 kb.
2.Problem on real device:
RMS is not working at all. I don't know if I need to give a permission for the handset (nokia n95).
Thanks.
In app, it is only storing charity companies into rms according to a selected country. So if a country is already selected, it must skip country list and then display company list in every restart.
In below code, rms_Check() method is to check the data in order to open country or company list frame.
public class X {
private static RecordStore rs =null;
private static Vector rms_Vector = new Vector();
static final String REC_STORE ="db_1";
public X() {
}
public void openRecStore(){
try {
rs = RecordStore.openRecordStore(REC_STORE, true);
System.out.println("open record store");
} catch (Exception e)
{
db(e.toString()+" in openRecStore");
}
}
public void closeRecStore(){
try {
rs.closeRecordStore();
} catch (Exception e) {
db(e.toString()+" in closeRecStore");
}
}
public void deleteRecStore()
{
if (RecordStore.listRecordStores()!=null){
try {
RecordStore.deleteRecordStore(REC_STORE);
} catch (Exception e) {
db(e.toString()+" in deleteRecStore");
}
}
}
public void writeRecord(String str) throws UnsupportedEncodingException
{
byte[] rec = str.getBytes("UTF-8");
try {
rs.addRecord(rec, 0, rec.length);
System.out.println("write record store");
} catch (Exception e) {
db(e.toString()+" in writeRecord");
}
}
public void readRecord()
{
try {
// Intentionally it is too small to test code
byte[] m_enc = new byte[5];
byte[] recData = new String(m_enc).getBytes("UTF-8");
int len;
for(int i =1; i<= rs.getNumRecords(); i++){
if(rs.getRecordSize(i)> recData.length)
recData = new byte[rs.getRecordSize(i)];
len = rs.getRecord(i, recData, 0);
System.out.println("Record #"+i+":"+new String(recData, 0, len));
System.out.println("------------------------");
rms_Vector.addElement(new String(recData, 0, len));
}
} catch (Exception e) {
db(e.toString() +" in readStore");
}
}
private void db(String str)
{
System.out.println("Msg:"+str);
}
public Vector rms_Array(){
return this.rms_Vector;
}
public boolean rms_Check(){
if(this.rms_Vector.size()>0){
System.out.print("rms_check: true");
// if true it will display company list every time
return true;
}else{
System.out.print("rms_check: false");
//if false it will display country list then company list
return false;
}
}
}
Use this
private RecordStore rs = null; // Record store
public String REC_STORE = "RSM name"; // Name of record store
public int record_max=0;
public void openRecStore(){
try{
rs = RecordStore.openRecordStore(REC_STORE, true );
}catch (Exception e){}
}
public void closeRecStore(){
try{
rs.closeRecordStore();
}catch (Exception e){}
}
public void deleteRecStore(){
if (RecordStore.listRecordStores() != null){
try{
RecordStore.deleteRecordStore(REC_STORE);
}catch (Exception e){}
}
}
public void writeRecord(String str){
byte[] rec = str.getBytes();
try{
rs.addRecord(rec, 0, rec.length);
}catch (Exception e){}
}
public void readRecords(){
try{
byte[] recData = new byte[5];
int len;
record_max=rs.getNumRecords();
for(int i = 1; i <= record_max; i++){
if(rs.getRecordSize(i) > recData.length){
recData = new byte[rs.getRecordSize(i)];
}
len = rs.getRecord(i, recData, 0);
file_name[i]=new String(recData, 0, len);
}
}catch (Exception e){}
}
you have file_name[] array of save data
for load actin commad use :
openRecStore();
readRecords();
for(int j=1;j<=record_max;j++ ) {
System.out.println("Record " + j + " : " + file_name[j]);
}
closeRecStore();
and save this :
openRecStore();
writeRecord(textField.getString());
closeRecStore();