I am trying to create a pet project for the summer, which requires a large amount of information. I think the best way to do this would be to store all the data in a text file, and proceed to pull the necessary information from that file when it's called upon. My question, though, is how to pull specific sets of information, and then proceed to store parts of that into an array perhaps or some other data structure which would allow for that to be more easily accessed during the execution of the program. The text file would have hundreds (if not thousands) of "sets" of data, and each "set" will have multiple parts. For example,
ID001 Name Data1 Data2 Data3 TypeData
Where ID001 would just be an index, the name would be a string, the three "Data" would be integers, and the TypeData would be a String (for example). What is the best way to go about taking all that information (there'll actually be more data per "set" but for simplicity's sake let's go with just this) and separating it so each part is usable by a different part of the program? Is this even the right way to go about doing something like this? I was originally imagining something along the lines of a spreadsheet but I don't know how to use something quite like that as I/O for a program.
Here's one possible way of reading a file and getting just the "chunks":
import java.io.*;
import java.util.Scanner;
public class ScanXan {
public static void main(String[] args) throws IOException {
Scanner s = null;
try {
s = new Scanner(new BufferedReader(new FileReader("xanadu.txt")));
while (s.hasNext()) {
System.out.println(s.next());
}
} finally {
if (s != null) {
s.close();
}
}
}
}
You can take a look at the Java Scanner Tutorial for other ideas.
Related
like the question how would I use a file object taken from the File class
https://docs.oracle.com/en/java/javase/12/docs/api/java.base/java/io/File.html
and use a scanner object wrapped around this to read the file,
then say a example like this is contained in the file,
Student{name=Jill Gall,age=21,gpa=2.98}
separate it into fields, skip next step as I just have to call the setters here, and then set the values
I then to save the fields as a Student Object and then save those in a array that I can return?
I'm not really looking for a solution to the entire problem here I'm just wondering as to what the syntax is for calling a scanner object wrapped around a File object to read it, I can use substring to grab the fields to separate and save them onto the new fields, and I'm pretty sure I can just use a for loop to load these onto a array that i can return, the only reason I listed out the entire problem for you guys is so I can give you guys the most details about the task as I can give here
right now my best attempt is this
Scanner n = new Scanner(System.in);
n.commandgoeshere?(filename);
how would I get the scanner to output the data so that i can take a substring and do the stuff i need to do above?
You have to provide an input stream in the constructor of the scanner, atm you are providing the system input stream (from the console) to the scanner. I think something like this is what you are looking for:
File file = new File("");
try {
Scanner scanner = new Scanner(file);
while (scanner.hasNext()) {
String nextLine = scanner.nextLine();
// or use regex ?
String extractedPattern = scanner.next("some pattern");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
I am writing a small java method that needs to read test data from a file on my win10 laptop.
The test data has not been formed yet but it will be text based.
I need to write a method that reads the data and analyses it character by character.
My questions are:
what is the simplest format to create and read the file....I was looking at JSON, something that does not look particularly complex but is it the best for a very simple application?
My second question (and I am a novice). If the file is in a text file on my laptop.....how do I tell my java code where to find it....how do I ask java to navigate the win10 operating system?
You can also map the text file into java objects (It depends on your text file).
For example, we have a text file that contains person name and family line by line like:
Foo,bar
John,doe
So for parse above text file and map it into a java object we can :
1- Create a Person Object
2- Read and parse the file (line by line)
Create Person Class
public class Person {
private String name;
private String family;
//setters and getters
}
Read The File and Parse line by line
public static void main(String[] args) throws IOException {
//Read file
//Parse line by line
//Map into person object
List<Person> personList = Files
.lines(Paths
.get("D:\\Project\\Code\\src\\main\\resources\\person.txt"))
.map(line -> {
//Get lines of test and split by ","
//It split words of the line and push them into an array of string. Like "John,Doe" -> [John,Doe]
List<String> nameAndFamily = Splitter.on(",").trimResults().omitEmptyStrings().splitToList(line);
//Create a new Person and get above words
Person person = new Person();
person.setName(nameAndFamily.get(0));
person.setFamily(nameAndFamily.get(1));
return person;
}
).collect(Collectors.toList());
//Process the person list
personList.forEach(person -> {
//You can whatever you want to the each person
//Print
System.out.println(person.getName());
System.out.println(person.getFamily());
});
}
Regarding your first question, I can't say much, without knowing anything about the data you like to write/read.
For your second question, you would normally do something like this:
String pathToFile = "C:/Users/SomeUser/Documents/testdata.txt";
InputStream in = new FileInputStream(pathToFile);
As your data gains more complexity you should probably think about using a defined format, if that is possible, something like JSON, YAML or similar for example.
Hope this helps a bit. Good luck with your project.
As for the format the text file needs to take, you should elaborate a bit on the kind of data. So I can't say much there.
But to navigate the file system, you just need to write the path a bit different:
The drive letter is a single character at the beginning of the path i.e. no colon ":"
replace the backslash with a slash
then you should be set.
So for example...
C:\users\johndoe\documents\projectfiles\mydatafile.txt
becomes
c/users/johndoe/documents/projectfiles/mydatafile.txt
With this path, you can use all the IO classes for file manipulation.
I've written my own 3D Game Engine and started writing a game. I am using OBJ-Models that use the TurboSquid Royalty Free License
Basically, it says that I can use their OBJ-Files but have to implement something that avoids the users to extract the OBJ-Files out of my program.
I've written a converter that extracts the information out of the OBJ-File and creates several float/integer arrays [vertices, vertexCoords, normals, tangents..., indices]
These arrays will be used later for creating the VAOs / VBOs. So my idea was to create a Java class called OBJModelData that contains these arrays. OBJModelDataimplements Serializable. My attempt was to save the class into a file and use them instead of the OBJ-File so that the user cannot see and use the content.
My attempt looks like this:
public void writeToFile(String file){
File f = new File(OBJLoader.RES_LOC+ file +".dat");
try {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));
out.writeObject(this);
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
This results in a file called modelName.dat and looks like this:
Obviously reverse engineering must be done the recreate my arrays. I just do not like the way its written. For example the class that has been serialized is written in the first line. If someone somehow manages the get the source files of my engine by doing some reverse engineering on that he could easily read the file.
Is my method save enough to avoid recreating the obj files and can I still use this method to fulfill the license conditions or is there any other way that is normally used (e.g. in other games/engines) ?
The end of your quote says: "without reverse engineering", so you do not need carry about reverse engineering. You need only "translate" from OBJ to another format of your creation, like you do.
So I'm in the process of developing a Java IRC bot as a bit of a side project for a friend of mine, and while development is going well, I'm a little unsure as how to save the current state of certain variables in between sessions. It doesn't have a GUI, so I didn't think that it would be too complex, but my searching efforts have been futile thus far.
Thanks.
It will depend on the sort of variables you want to keep, but all methods will require you to write some sort data to a file.
If you only need to keep a handful of variables, you could consider implementing a .config file that could be a simple delimited text file.
If it's an entire object that you want to keep track of, say, a player in an irc game, one option you have is to parse the object into JSON, and save it to a textfile, for reading later. You can use Gson for this
example for a 'player' object:
public String savePlayer(String playerName){
Gson gsonPretty = new GsonBuilder().setPrettyPrinting().create();
String playerFile = System.getProperty("user.dir")+"\\players\\"+playerName;
String jsonplayers = gsonPretty.toJson(players.get(playerName));
try{
FileWriter writer = new FileWriter(playerFile+".json");
writer.write(jsonplayers);
writer.close();
return "Player file saved successfully!";
}catch(Exception e){
e.printStackTrace();
}
return "Something went wrong";
}
you can then create a load method that either has the file name hard coded, or a string input to determine which file to load, and use something like:
playerFromJson = gson.fromJson(jsonString, Player.class);
to use that object in the code
I have a file that contains bytes, chars, and an object, all of which need to be written then read. What would be the best way to utilize Java's different IO streams for writing and reading these data types? More specifically, is there a proper way to add delimiters and recognize those delimiters, then triggering what stream should be used? I believe I need some clarification on using multiple streams in the same file, something I have never studied before. A thorough explanation would be a sufficient answer. Thanks!
As EJP already suggested, use ObjectOutputStream and ObjectInputStream an0d wrap your other elements as an object(s). I'm giving as an answer so I could show an example (it's hard to do it in comment) EJP - if you want to embed it in your question, please do and I'll delete the answer.
class MyWrapedData implements serializeable{
private String string1;
private String string2;
private char char1;
// constructors
// getters setters
}
Write to file:
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(fileName));
out.writeObject(myWrappedDataInstance);
out.flush();
Read from file
ObjectInputStream in = new ObjectInputStream(new FileInputStream(fileName));
Object obj = in.readObject();
MyWrapedData wraped = null;
if ((obj != null) && (obj instanceof MyWrappedData))
wraped = (MyWrapedData)obj;
// get the specific elements from the wraped object
see very clear example here: Read and Write
Redesign the file. There is no sensible way of implementing it as presently designed. For example the object presupposes an ObjectOutputStream, which has a header - where's that going to go? And how are you going to know where to switch from bytes to chars?
I would probably use an ObjectOutputStream for the whole thing and write everything as objects. Then Serialization solves all those problems for you. After all you don't actually care what's in the file, only how to read and write it.
Can you change the structure of the file? It is unclear because the first sentence of your question contradicts being able to add delineators. If you can change the file structure you could output the different data types into separate files. I would consider this the 'proper' way to delineate the data streams.
If you are stuck with the file the way it is then you will need to write an interface to the file's structure which in practice is a shopping list of read operations and a lot of exception handling. A hackish way to program because it will require a hex editor and a lot of trial and error but it works in certain cases.
Why not write the file as XML, possibly with a nice simple library like XSTream. If you are concerned about space, wrap it in gzip compression.
If you have control over the file format, and it's not an exceptionally large file (i.e. < 1 GiB), have you thought about using Google's Protocol Buffers?
They generate code that parses (and serializes) file/byte[] content. Protocol buffers use a tagging approach on every value that includes (1) field number and (2) a type, so they have nice properties such as forward/backward compatability with optional fields etc. They are fairly well optimized for both speed and file size, adding only ~2 bytes of overhead for a short byte[], with ~2-4 additional bytes to encode the length on larger byte[] fields (VarInt encoded lengths).
This could be overkill, but if you have a bunch of different fields & types, protobuf is really helpful. See: http://code.google.com/p/protobuf/.
An alternative is Thrift by Facebook, with support for a few more languages although possibly less use in the wild last I checked.
If the structure of your file is not fixed, consider using a wrapper per type. First you need to create the interface of your wrapper classes….
interface MyWrapper extends Serializable {
void accept(MyWrapperVisitor visitor);
}
Then you create the MyWrapperVisitor interface…
interface MyWrapperVisitor {
void visit(MyString wrapper);
void visit(MyChar wrapper);
void visit(MyLong wrapper);
void visit(MyCustomObject wrapper);
}
Then you create your wrapper classes…
class MyString implements MyWrapper {
public final String value;
public MyString(String value) {
super();
this.value = value;
}
#Override
public void accept(MyWrapperVisitor visitor) {
visitor.visit(this);
}
}
.
.
.
And finally you read your objects…
final InputStream in = new FileInputStream(myfile);
final ObjectInputStream objIn = new ObjectInputStream(in);
final MyWrapperVisitor visitor = new MyWrapperVisitor() {
#Override
public void visit(MyString wrapper) {
//your logic here
}
.
.
.
};
//loop over all your objects here
final MyWrapper wrapper = (MyWrapper) objIn.readObject();
wrapper.accept(visitor);