Android: Reading a file using InputStream character by character - java

Solved: The code I originally posted is fine, I just tried reading a txt file from a directory in assets without adding the directory's name in the "path" string under the false assumption "getAssets()" gets all assets from all subdirectories in assets.
I am making a game that uses cards with a name and description, the name and description are read from a .txt file in the assets folder. The method is made so it reads everything between '$' and '#' as the name, and '#' and '#' as the description. I wrote the original method in Eclipse (console application) and it worked like a charm. Then I transferred it to Android Studio, added context (since the method is in a class file) and AssetManager, etc and followed instructions from other similar stackoverflow questions but for some reason it just won't work.
Here is the code:
public void readFile(String p) throws IOException {
// Path of the directory
String path = new String(p);
// AssetManager opens assets
AssetManager am = con.getAssets();
// Open file
InputStream i_s = am.open(path);
// StringBuilders store the text read for specific members
StringBuilder _name = new StringBuilder(""); // Records name of card from file
StringBuilder _desc = new StringBuilder(""); // Records description of card from file
// "c" stores each character at a time
char c;
// Main loop that reads entire file
while(i_s.available() > 0) {
c = (char) i_s.read();
if(c=='$') {
c = (char) i_s.read(); // Sends to next character so it doesn't save '$'
while(c!='#') // Loop saves everything between '$' and '#'
{_name.append(c); c = (char) i_s.read();}
}
else if(c=='#') {
c = (char) i_s.read(); // Sends to next character so it doesn't save '#'
while(c!='#') // Loop saves everything between '#' and '#'
{_desc.append(c); c = (char) i_s.read();}
}
}
i_s.close();
// Sets read info into Class properties
this.setName(_name);
this.setDesc(_desc);
}
The method is in CardAction card,a subclass of Card. The set methods are in the Card class.
public void setName(StringBuilder sb) {
this.name = sb.toString();
}
public void setDesc(StringBuilder sb) {
this.desc = sb.toString();
}
Every time I test this (by calling the get methods for name and desc) it return empty strings. What am I doing wrong here?
Additional info: All the Card subclasses inherit the context "con" from Card superclass which passes the context from the main activity as a parameter in the Card constructor, so I am 100% sure Context and AssetManager are working fine.
Edit: Code that calls the readFile method from main activity
String str;
Turn t = new Turn(3, 40, t_o_d, names, true, 1, con);
// chooseFile returns String of randomly chosen file
// name from the assets folder (randomly "draw" card), works
str = t.chooseFile(1);
CardAction ca = new CardAction(con); //Passes context as parameter for constructor
try {ca.readFile(str);}
catch(IOException e1) {}
// cardName and cardDesc are TextViews I set just for testing the readFile method
cardName.setVisibility(View.VISIBLE);
cardDesc.setVisibility(View.VISIBLE);
cardName.setText(ca.getName());
cardDesc.setText(ca.getDesc());

Solved. the method is fine, what my problem was that I tried to open txt files located in their own folders in assets, so I just added another String parameter to the method (for the directory) and concatenated them (adding "/" between them).
Well, considering this was a solution for a completely other problem, I'm still glad this works so anyone struggling with reading files character by character can refer to the code I originally posted :)

Related

StringBuilder split not working on some files

I'm trying to get the parent directory of each file and put it into a ListView in Java fx.
It does work, but not for some file names, and I cannot understand why.
Iterator<String> listIterator = loadedFiles.iterator();
StringBuilder listItem = null;
while (listIterator.hasNext()) {
File listFile = new File(listIterator.next());
listItem = new StringBuilder(Arrays.toString(listFile.getAbsolutePath().split(listFile.getName())));
toDir(listItem);
ctrl.fileList.getItems().add(listItem.toString());
}
gets the File Path, and cuts off the filename.
toDir:
private void toDir(StringBuilder builder) {
builder.deleteCharAt(builder.length() - 1);
builder.deleteCharAt(0);
if (builder.charAt(builder.length() - 1) == '\\') {
builder.deleteCharAt(builder.length() - 1);
}
}
Removes the Array brackets and the last '\'
The given file paths are:
C:\Users\Test\Downloads\048815 - Kopie (2).jpg
C:\Users\Test\Downloads\048815 - Kopie (3).jpg
C:\Users\Test\Downloads\048815 - Kopie (4).jpg
C:\Users\Test\Downloads\048815 - Kopie.jpg
C:\Users\Test\Downloads\048815.jpg
The first tree files, the ones with the () in names do not work, the file name is still in the String and added to the list, only the last two ones get the file name removed.
Your immediate problem is that you are misusing String#split(). The argument to split() is a regular expression, in which parentheses are grouping meta-characters. You do not want to use split() at all here. In fact, you are much better off using the path manipulation methods in java.nio.file.Path.
for (String fileName : loadedFiles)
{
Path filePath = Path.of(fileName);
Path directory = filePath.getParent();
ctrl.fileList.getItems().add(directory.toString());
}
Once you're comfortable with the API, you can reduce this to
for (String fileName : loadedFiles)
{
ctrl.fileList.getItems().add(Path.of(filename).getParent().toString());
}

Cannot find a image file that exists in java

I have written a function which takes in a BufferedImage and compares it to a pre-existing image in my hard drive checking if they are same or not.
public boolean checkIfSimilarImages(BufferedImage imgA, File B) {
DataBuffer imgAdata = imgA.getData().getDataBuffer();
int sizeA = imgAdata.getSize();
BufferedImage imgB = null;
try {
imgB = ImageIO.read(B);
} catch (IOException ex) {
Logger.getLogger(SupportClass.class.getName()).log(Level.SEVERE, null, ex);
}
DataBuffer imgBdata = imgB.getData().getDataBuffer();
int sizeB = imgBdata.getSize();
if(sizeA == sizeB) {
for(int i = 0; i < sizeA; i++) {
if (imgAdata.getElem(i) != imgBdata.getElem(i)) {
return false;
}
}
}
return true;
}
This throws IOException "Cant read input file". Idk why this is happening. I am calling the function like this...
while(support.checkIfSimilarImages(currentDisplay, new File(pathToOriginalImage)) == false) {
System.out.println("Executing while-loop!");
bot.delay(3000);
currentDisplay = bot.createScreenCapture(captureArea);
}
where,
String pathToOriginalImage = "‪‪‪‪C:\\Users\\Chandrachur\\Desktop\\Home.jpg";
I can see that the path is valid. But as I am testing it for File.exists() or File.canRead() or File.absoluteFile().exists() inside the checkIfSimilarImages function and everything is returning false.
I have researched my question here and tried out these suggestions:
It is not only for this location, I have tried a variety of other locations but in vain. Also it is not a problem where I have hidden file extensions and the actual file might be Home.jpg.jpg .
The only thing that might be is that permissions might be different. I dont really know how to verify this, but there is no reason it should have some permission which is not readable by java. It is just another normal jpg file.
Can it be because I am passing the file object reference into a function so in this process somehow the reference is getting modified or something. I just dont know. I am running out of possibilities to test for...
The whole stack trace is as follows:
javax.imageio.IIOException: Can't read input file!
at javax.imageio.ImageIO.read(ImageIO.java:1301)
at battlesbot.SupportClass.checkIfSimilarImages(SupportClass.java:77)
at battlesbot.AutomatedActions.reachHomeScreen(AutomatedActions.java:72)
at battlesbot.BattlesBot.main(BattlesBot.java:22)
Exception in thread "main" java.lang.NullPointerException
at battlesbot.SupportClass.checkIfSimilarImages(SupportClass.java:81)
at battlesbot.AutomatedActions.reachHomeScreen(AutomatedActions.java:72)
at battlesbot.BattlesBot.main(BattlesBot.java:22)
C:\Users\Chandrachur\AppData\Local\NetBeans\Cache\8.2\executor-snippets\run.xml:53: Java returned: 1
BUILD FAILED (total time: 11 seconds)
I am on Windows 10, IDE is NetBeans.
UPDATE:
Huge thanks to #k5_ . He told me to paste this in path and it worked.
"C:/Users/Chandrachur/Desktop/Home.jpg";
It seems some invisible characters were in the path. But I still don't understand what that means.
Usually this kind of problem lies with access problem or typos in the filename.
In this case there were some invisible unicode characters x202A in the filename. The windows dialog box, the file path was copied from, uses them for direction of writing (left to right).
One way of displaying them would be this loop, it has 4 invisible characters at the start of the String. You would also see them in a debugger.
String x = "‪‪‪‪C:\\Users\\Chandrachur\\Desktop\\Home.jpg";
for(char c : x.toCharArray()) {
System.out.println( c + " " + (int) c);
}

Generating custom text files in java

public class ScriptCreator {
public static void main(String[] args) throws IOException {
#Choose the CSV file that I am importing the data from
String fName = "C:\\Users\\MyUser\\Downloads\\CurrentApplications (1).csv";
String thisLine;
int count = 0;
FileInputStream fis = new FileInputStream(fName);
DataInputStream myInput = new DataInputStream(fis);
int i = 0;
#Prints the List of names in the CSV file
while((thisLine = myInput.readLine()) != null){
String strar[] = thisLine.split(",");
Printer(strar[0]);
}
}
public static void Printer(String arg) throws IOException{
#Want to pull from the String strar[0] from above
#Says that it cannot be resolved to a variable
String name = arg;
String direc = "C:/Users/MyUser/Documents/";
String path = "C:/Users/MyUser/Documents";
Iterable<String> lines = Arrays.asList("LOGIN -acceptssl ServerName","N " + name + " " + direc ,"cd " + name,"import " + path + "*.ppf" + " true","scan", "publishassessase -aseapplication " + name,"removeassess *","del " + name );
Path file = Paths.get(name + ".txt");
Files.write(file, lines, Charset.forName("UTF-8"));
}
}
Hello everyone and thank you in advance for any help that you may be able to give me. I am trying to create a java program that will pull names from a CSV file and take those names to generate custom outputs for text files. I am having a hard time being able to set a variable that I can use to grab the names that are being printed and using them to generate a text file by setting the name variable.
I am also going to need some help in making sure that it creates the amount of scripts for the amount of names in the CSV file. Ex. 7 names in CSV makes 7 custom .txt files, each with its appropriate name.
Any help is greatly appreciated!
Edit: I have updated my code to match the correction that was needed to make the code work.
It looks like you have some scoping issues. Whenever you declare a variable, it only exists within the boundaries of its closest set of braces. By declaring strar in your main method, the only place you can explicitly use it is within your main method. Your Printer() method doesn't have any previous mention of strar, and the only way it can know about it is by passing it as an argument to the function.
i.e.
Printer(String[] args)
Or, better yet:
Printer(String arg)
and then call it in your while loop with
Printer(strar[0]);
Also, your Printer method begins with a "for each" loop called on strar[0], which is not a valid target for a foreach loop anyway, because if I recall correctly, String isn't an Iterable object. If you implemented the Printer function in the way I recommended, you won't need a for each loop anyway, as there will only be one name passed at a time.

How do I implement #params filetype into this seleciton of code?

I am currently working on a word search program for my Java class, and I thought I would do some research on other similar programs before I get started. (See how they work before I write my own version.) I have stumbled across this program:
“Java Word Search Solver” by tmck-code via Code Review, Feb 2015.
It looks very well written, but I cannot figure out how to input my file-name for the puzzle and word list method.
Example:
/**
* A method that loads a dictionary text file into a tree structure
* #param filename The dictionary file to load
* #return The Red-Black tree containing the dictionary
*/
private static ArrayList<String> loadDict(String filename) {
ArrayList<String> dict = new ArrayList<String>();
try {
BufferedReader in = new BufferedReader(
new FileReader(filename));
String word;
while( (word = in.readLine()) != null ) {
dict.add(word);
}
} catch( IOException e ) {
System.err.println("A file error occurred: " + filename );
System.exit(1);
}
return dict;
}
Where in this selection of code do I put my file name (wordlist.txt)?
You do not put this anywhere in the code. I read a little through to code in your link. The path of your file gets passed to programm as you call it.
If you call it via a console (e.g. cmd.exe) it should look somehow like this:
C:\Users\yourName> java WordSearch.java "/path/to/your/file.txt"
You do not put anything of the information in the code itself. The programm in your link just uses the console arguments

Giving another class variablevalues before the variables are declared in Java

I am trying to pass values to variables that probably are not declared yet.
From my main source class I am giving another's class some values, but later on it seems like the values are gone.
Source code:
server.java (main):
public class server {
public static void main(String[] args) {
//Print a simple message to the user to notify there is something going on...
System.out.println("Starting server, please wait...");
//Connecting all class files to the server.
filehandler filehandlerclass = new filehandler();
networking networkingclass = new networking();
//End of class files connecting.
//Preparing the filehandler's file information to open a new filestream.
filehandlerclass.filetohandlename = "server";
filehandlerclass.filetohandleextention = "ini";
filehandlerclass.filetohandlepath = "configs\\";
//Request a new filestream using the filehandler's file variables.
filehandlerclass.openfilestream(filehandlerclass.filestream, filehandlerclass.filetohandle);
//Checks if the filehandler has tried to open a filestream.
if(filehandlerclass.filestreamopen == true) {
//Request a check if the filestream was opened sucessfully.
filehandlerclass.filestreamexists(filehandlerclass.filestream);
}
//If the filehandler has not tried to open a filestream...
else {
System.out.println("Error: The filehandler does not seem to have tried to open a filoestream yet.");
System.out.println("A possibility is that the server could not call the method from the filehandler properly.");
}
//Checks if the boolean "filestreamexists" from the filehandlerclass is true.
if(filehandlerclass.filestreamexists(filehandlerclass.filestream) == true) {
//The filestream seems to exist, let's read the file and extract it's information.
filehandlerclass.readfile(filehandlerclass.filestream);
}
else {
filehandlerclass.openfilestream(filehandlerclass.filestream, filehandlerclass.filetohandle);
}
}
}
filehandler.java:
//Imports the java.io library so the filehandler can read and write to text files.
import java.io.*;
public class filehandler {
//Variables for the filehandler class.
public String filetohandlename;
public String filetohandleextention;
public String filetohandlefullname = filetohandlename + "." + filetohandleextention;
public String filetohandlepath;
public String filetohandle = filetohandlepath + filetohandlefullname;
//Boolean that is true if the filehandler's "openfilestream"-method has tried to open a filestream.
//Is false as long as none filestreams have been touched.
public boolean filestreamopen = false;
//Declares a variable for the filestream to access text files.
public File filestream;
//End of variable list.
//Called to open a filestream so the server can load properties from text files.
public void openfilestream(File filestream, String filetohandle) {
//Tell the user that a filestream is about to be opened.
System.out.println("Opening filestream for \"" + filetohandlefullname + "\"...");
//Open a filestream called "filestream" using the variable "filetohandle"'s value
//as information about wich file to open the filestream for.
filestream = new File(filetohandle);
//Turn the boolean "filestreamopen" to true so next time the server checks it's
//value, it knows if the filehandler has tried to open a filestream.
filestreamopen = true;
}
//Boolean that checks if the filestream exists.
public boolean filestreamexists(File filestream) {
//Tell the user that a check on the filestream is going on.
System.out.println("Checking if filestream for \"" + filetohandlefullname + "\" exists...");
//If the filestream exists...
if(filestream.exists()) {
//Tell the user that the filestream exists.
System.out.println("Filestream for \"" + filetohandlefullname + "\" exists!");
//Make the boolean's value positive.
return true;
}
//If the filestream does not exist...
else {
//Tell the user that the filestream does not exist.
System.out.println("Filestream for \"" + filetohandlefullname + "\" does not exist!");
//Make the boolean's value negative.
return false;
}
}
//Called to read files and collect it's information.
public void readfile(File filestream) {
//Checks if the file that is going to be read is a configuration file.
if(filetohandleextention == "ini") {
//Tell the user that a configuration file is going to be read.
System.out.println("Extracting information from the configuration file \"" + filetohandle + "\".");
}
}
}
networking.java:
public class networking {
}
Problem:
server.java is going to serve commands to the source files and tell them what to do.
The source files are not going to act on their own unless server.java has given them a command.
This way I am planning to be able to write simple function calls in server.java to do greater tasks from the different source files.
server.java seems to pass the variables "filetohandlename", "filetohandleextention" and "filetohandlepath" before the variables are declared and when they get declared, they are declared with "null" as value.
Result:
I get no errors when I compile it.
All I think is happening is a miss match with giving the variables that specifies the file that is going to be read's proper values.
It also throws an exception which I have not been careing to look into for now, either it's because "null.null" does not exist or that I wrote the code wrong.
Final request:
Does anybody know if I can make a method for recieving the variables values
or if there is another more proper way around?
Could I probably make an array of the variables in server.java and collect the values from that array?
Thank you so much for your time.
This:
public String filetohandlename;
public String filetohandleextention;
public String filetohandlefullname = filetohandlename + "." + filetohandleextention;
initialises the first two variables to null, and the third to "null.null". Note that if you change one of the component variables that have made up filetohandlefullname, it won't then change the value of filetohandlefullname. If you want that to happen, then filetohandlefullname should be replaced by a method performing the appending operation.
This:
public void openfilestream(File filestream, String filetohandle)
passes a different variable filetohandle into the method. That variable is distinct from this.filetohandle.
I think there's a numberof issues with this code (above) and I'd do the following.
replace variables instantiated via other variables with methods that perform this dynamically. That way, when you change var1 that you'd expect to change the value of var2, that will happen automatically via a method return. e.g create a private method getFileToHandleFullName() and bin the corresponding variable
scope class members with this
where possible, make those members final so you don't inadvertently change them
This line
public String filetohandlefullname = filetohandlename + "." + filetohandleextention;
is executed when you instantiate the class (ie filehandler filehandlerclass = new filehandler();). At that point in time both variables are unset, thus filetohandlefullname is initialized to null.null
But there's a number of other problems with your code as well, like
//Request a new filestream using the filehandler's file variables.
filehandlerclass.openfilestream(filehandlerclass. filestream,filehandlerclass.filetohandle);
eg you're passing parameters that are fields from the same instance. That's totally useless as the method already has access to those, and it's very confusing.
And maybe slightly controversial:
//Make the boolean's value positive.
return true;
Comments are only useful if they clarify code that without them would be less obvious, and they have to be 100% true and not, as happens so often, what the program wishes the code would do. In this specific case neither of these conditions is fulfilled as the comment doesn't clarify what's going on, and actually the method's return value is set, not some nondescript "boolean's value"

Categories

Resources