I am making a Flight reservation system for my course project and I am having problems using StringBuilder which my teacher asked me to use in my code.
I wrote this method to delete a customer's data from a text file which I am using for storing the customer's details and the ticket number I assigned to them now this method takes the ticket number and searches in the text file and delete that entry (line of text file).
The text file is formatted in this way
(name + "\t" + socialNum + "\t" + cellNum + "\t" + tickNum + "\n")
The problem is that when I check the text file manually I see that The file was correctly formatted before but after running this method it is not.( The last escape sequence i.e "\n" is not being printed to the file).
public static void deleteData(String b) throws FileNotFoundException {
Scanner input = new Scanner(Basic.file); // Text file used as Database
while (input.hasNext()) {
String a = input.nextLine();
a = a.trim();
a = a.toUpperCase(Locale.ROOT);
if (a.contains(b)) {
continue;
}
Basic.c.append(a).append("\n"); // c is StringBuilderObj
}
if ((Basic.c.toString()).equals("")) {
System.out.println("Invalid Ticket Number.");
} else {
try (PrintWriter out = new PrintWriter(Basic.file)) {
String result = Basic.c.toString();
out.println(result);
}
}
Related
I am currently stuck with a problem. I am supposed to write a programm that is able to search for a string in a .txt file given as argument. The programm must return the row and the column of the found string.
I am struggling to find a way to achieve that and have no idea how to go on. I would be very happy to hear from you.
Here is my attempt in tackling with my task:
- I thought about saving the content of a file via a buffered reader in a string array, but that does not seem to work since I cannot define the length of the array from the beginning
- I also thought about saving the content of the file via a buffered reader in a string and then split this string in characters. However I am not sure how I will be able to retreieve the rows in the original file then.
This is the non-functional code that I have at the moment:
public class StringSearch{
public static void main(String[] args){
if(args.length > 0){
BufferedReader br = null;
String text = null;
try{
br = new BufferedReader(new FileReader(args[0]));
// attempt of saving the content of the "argument" file in a string array and then in a string
String[] lines = new String[]; // I know this does not work like this
for( int i = 0; i < lines.length; i++){
lines[i] = br.readLine;
text = text + lines[i];
i++;
}
text.split("\r\n");
} catch (IOException ioe){
ioe.printStackTrace();
} finally{
if (br != null) {
try{
br.close();
}catch (IOException ioe){
ioe.printStackTrace();
}
}
}
}
}
}
You can do it as follows:
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
if (args.length != 2) {
System.out.println("The correct syntax to use this program is: java Main <filename.txt> <text-to-search>");
return;
}
Scanner scanner;
File file = new File(args[0]);
int rowCount = 1, index;
String line;
// Map to collect row and col info of the search string
Map<String, String> lineColMap = new HashMap<String, String>();
if (!file.exists()) {
System.out.println("The file, " + args[0] + " does not exist");
return;
}
try {
scanner = new Scanner(file);
while (scanner.hasNextLine()) {// Loop until the last line in the file
line = scanner.nextLine();// Read a line from the file
index = line.indexOf(args[1]);// Find if the string exists in the line
if (index != -1) {// If the string exists
// Put the row and col info of the search string into the map
lineColMap.put("Row: " + rowCount, "Column: " + index);
}
rowCount++;// Increase the row count
}
} catch (Exception e) {
System.out.println("Error occured while processing the file");
e.printStackTrace();
}
if (lineColMap.entrySet().size() > 0) {// If there is at least one entry collected into the map
System.out.println("'" + args[1] + "' exists in " + args[0] + " as follows:");
for (Map.Entry<String, String> entry : lineColMap.entrySet()) {
System.out.println(entry.getKey() + ", " + entry.getValue());
}
} else {
System.out.println("'" + args[1] + "' does not exist in " + args[0]);
}
}
}
A sample run: java Main input.txt of
'of' exists in input.txt as follows:
Row: 1, Column: 51
Row: 2, Column: 50
Row: 3, Column: 50
Row: 5, Column: 71
The content of input.txt is as follows:
Stack Overflow is a question and answer site for professional and enthusiast programmers.
It is a privately held website, the flagship site of the Stack Exchange Network, created in 2008 by Jeff Atwood and Joel Spolsky.
It features questions and answers on a wide range of topics in computer programming.
It was created to be a more open alternative to earlier question and answer sites such as Experts-Exchange.
The name for the website was chosen by voting in April 2008 by readers of Coding Horror, Atwood's popular programming blog.
The logic in the code is straight forward and I believe, you should be able to understand it in the first reading. Feel free to comment in case of any doubt.
Here's one approach -
Let's consider a counter which holds a counter for all the
readLine() method invocations - representing the "row" in the .txt
file. So, increment the counter after every readLine call in the
while loop.
Next, split the line on " " (space) to get an array of each word in the
line. Then, you could iterate over this array and match the word to
the search string. The position of array index at the time the match
was found will represent the "column".
I want to send studentGrade array to "calculate" method to calculate the average of grades but if the first line of text file is parameter, I can't. When the "if" method running, it goes back to while loop, even though two strings are equal.
I've tried to change the first line of .txt, in case of there is a problem. But the result was the same. It never does compare if the wanted person is in the first line.
static int studentNumber = 0;
static String[] studentGrade;
static String studentName = "";
static void makeList(String name) {
try(Scanner sc = new Scanner(new BufferedReader(new FileReader("C:\\Users\\User\\Desktop\\new_1.txt")))) {
boolean flag = true;
while (sc.hasNextLine()) {
flag = true;
String studentLine = sc.nextLine();
studentGrade = studentLine.split(",");
studentName = studentGrade[0];
if (studentName.equalsIgnoreCase(name)){
calculate(studentGrade);
flag = false;
break;
}
}
if (flag)
System.out.println("Couldn't found!");
}
catch (FileNotFoundException e) {
System.out.println("An error occured when the file was tried to opened.");
}
}
static void calculate(String[] a) {
int note1 = Integer.parseInt(a[1]);
int note2 = Integer.parseInt(a[2]);
int note3 = Integer.parseInt(a[3]);
double avg = Math.ceil((double)(note1 + note2 + note3) / 3);
System.out.println(a[0] + "'s average is: " + (int)avg);
}
I expect the if case would be true and sent the array to "calculate" method. It does its job except the student is in the first line of .txt file. For example if user input is Michael, it says "Couldn't found!" but if the input is John, it gives its average.
//First lines of .txt file
Michael,70,90,20
John,90,80,60
Molly,60,30,50
I created a file with the values you are giving:
Michael,70,90,20
John,90,80,60
Molly,60,30,50
And when I try your code, it seems to work fine:
makeList("Michael");
makeList("John");
makeList("Molly");
return
60
77
47
My suspicion is that you have some kind of invisible character at the very beginning of your file, and that is what makes your equality fail. I encountered this kind of issue several time when parsing XML and the parser would complain that my file doesn't start with an XML tag.
Can you try to make a brand new file with these 3 lines and try your program again on this new file?
Here is a much simpler and clearer way to do this:
try (Stream<String> lines = Files.lines("C:\\Users\\User\\Desktop\\new_1.txt")) {
Optional<String[]> studentGradesOpt =
lines.map(line -> line.split(","))
.filter(row -> row[0].equalsIgnoreCase(name))
.findFirst();
studentGradesOpt.ifPresent(grades -> calculate(grades));
if (!studentGradesOpt.isPresent()) {
System.out.println("Couldn't find student " + name);
}
}
I've got a text file with one customer record per line. Each record is formatted as "ID num, first name, last name, dollar amount". I need to read a line of this text file based on the ID number entered by the user.
I've been following a Java ebook that does this by using the length of a single record and multiplying it by the ID number entered. The problem is, that only works if every record has the exact same length. My records do not truncate or pad out the first and last name, and the dollar amount ranges from two to five characters in length which means that the method that the book uses won't work.
Is there any way to read a specific line in a text file without requiring all the records to be the exact same length? I'd have thought that there would be a way to use the line separator character to do it.
For reference I'll put up the code that doesn't work due to my varying record sizes, in case it helps.
public static void main(String[] args)
{
Scanner keyboard = new Scanner(System.in);
Path filepath = Paths.get("U:\\Programming\\Java\\Chapter 13\\customersdata.txt");
String s = " , , , 00.00" + System.getProperty("line.separator");
final int RECSIZE = s.length();
byte[] data = s.getBytes();
ByteBuffer buffer = ByteBuffer.wrap(data);
FileChannel fc = null;
try {
fc = (FileChannel)Files.newByteChannel(filepath, READ, WRITE);
System.out.println("Enter an ID number to display the customer details for that ID. Or \"quit\".");
String idString = keyboard.nextLine();
while(!idString.equals("quit")) {
int id = Integer.parseInt(idString);
buffer = ByteBuffer.wrap(data);
fc.position(id * RECSIZE);
fc.read(buffer);
s = new String(data);
System.out.println("ID #" + id + " " + s);
System.out.println("Enter an ID number to display the customer details for that ID. Or \"quit\".");
idString = keyboard.nextLine();
}
fc.close();
}catch(Exception e) {
System.out.println("Error message: " + e);
}
}
EDIT: As the text file being read from could hypothetically contain tens of thousands of records, I can't use Sequential Access, if the ID number I need is near the bottom of the file, it would take an unacceptable amount of time to read them all, as such, the solution must be Random Access.
I've got a text file with one customer record per line. Each record is
formatted as "ID num, first name, last name, dollar amount". I need to
read a line of this text file based on the ID number entered by the
user.
and
Is there any way to read a specific line in a text file without
requiring all the records to be the exact same length?
In the main method at readData("33"), i hardcoded the id string. You can change it according to your data.txt and get the data.
data.txt
1 harry singh 456
2 lauren dat 25
33 pingle pooh 8797
10002 yogeshvari bahman 897461
parseTxt.java
import java.io.File;
import java.util.Scanner;
public class parseTxt {
private static Scanner fileReader ;
public static void main(String[] args)
{
try{
readData("33");
} catch(Exception e){
System.out.println("Exception : " + e);
}
}
private static void readData(String id) throws Exception{
fileReader = new Scanner(new File("E://data.txt"));
String cusId, fname, lname, dollar;
while(fileReader.hasNextLine()){
String line = fileReader.nextLine();
String[] lineParts = line.split(" ");
if(lineParts[0].equals(id)){ // lineParts[0] is ID NUMBER
cusId = lineParts[0];
fname = lineParts[1];
lname = lineParts[2];
dollar = lineParts[3];
System.out.println("Customer ID : #" + cusId);
System.out.println("First Name : " + fname);
System.out.println("Last Name : " + lname);
System.out.println("Dollar Amount : $" + dollar);
break;
} else {
System.out.println("This ID:" + id + " does not exist");
}
}
}
}
For Edited Question (search while keeping good performance)
source-1:
try (SeekableByteChannel ch = Files.newByteChannel(Paths.get("test.txt"))) {
ByteBuffer bb = ByteBuffer.allocateDirect(1000);
for(;;) {
StringBuilder line = new StringBuilder();
int n = ch.read(bb);
// add chars to line
// ... don't forget to break
}
}
It requires a bit of coding but it can be really faster because of ByteBuffer.allocateDirect. It allows OS to read bytes from file to ByteBuffer directly, without copying
source-2: Every answer on this link adds bits of information
Convert the search string ('are') to a byte-array in the same
encoding as the file.
Open a memory-mapped byte-buffer from a File-Channel on the file.
Scan the ByteBuffer, looking for matches to the search byte-array
count the newlines as you go.
close the ByteBuffer
source-3:
A simple technique that could well be considerably faster than indexOf() is to use a Scanner, with the method findWithinHorizon(). If you use a constructor that takes a File object, Scanner will internally make a FileChannel to read the file. And for pattern matching it will end up using a Boyer-Moore algorithm for efficient string searching.
source-4: Implementation of Boyer-Moore's String Search algorithm
I am sorry but I will leave the researching to you. If you ask my suggestion, I think GNU-Grep is faster of them all because it, too, uses Boyer-Moore's string search algorithm.
Hope this helps! correct me if i misunderstood your problem.
My code is used to create a file inside a folder of a directory, with the file containing a heading at the top based on what the user inputs.
import java.util.*;
import java.text.*;
import java.io.*;
public class setup {
public static void main(String[] args) {
Scanner userin = new Scanner(System.in);
int hwnum;
String hwsummary;
int period;
String name;
System.out.println("Enter name: ");
name = userin.next();
System.out.println("Enter APCS period: ");
period = userin.nextInt();
System.out.print("Enter HW number: ");
hwnum = userin.nextInt();
System.out.println("Enter HW summary: ");
hwsummary = userin.next();
System.out.println("Enter file name: ");
String hwname = userin.next();
hwname = hwname + ".java";
new File("/hw" + hwnum).mkdirs();
new File("/hw" + hwnum +"/" + hwname);
String filename;
filename = "\\hw" + hwnum + "\\" + hwname;
System.out.println("/*");
System.out.println(name);
System.out.println("APCS1 " + "pd" + period);
System.out.println("HW" + hwnum + " -- " + hwsummary);
System.out.println(getdate());
System.out.println("*/");
}
public static String getdate() {
DateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd");
Date date = new Date();
String todaydate;
todaydate = dateformat.format(date);
return todaydate;
}
}
The end result of the code, if give by the user should be a java file in a directory named "/hwxx" and should have a heading similar to:
/*
Name
APCS1 pdx
HW# - HWSUMMARY
DATE
*/
System.out.println() can't be used to write to a file, only to print text to the standard output stream. A FileWriter and BufferedWriter can be used instead to write to a file. Try replacing the last part of your main method with this:
try {
FileWriter outputStream = new FileWriter(filename);
try (BufferedWriter out = new BufferedWriter(outputStream)) {
out.write("/*");
out.newLine();
out.write(name);
out.newLine();
out.write("APCS1 pd" + period);
out.newLine();
out.write("HW" + hwnum + " -- " + hwsummary);
out.newLine();
out.write(getdate());
out.newLine();
out.write("*/");
}
} catch (IOException ex) {
// some sort of error message here
// this block will only be run if the program is unable to create or write to the specified file
}
Note that the write() method is the file-writing equivalent to print() rather than println(), so it's necessary to include the newline() method between each line of text to avoid having it all be written to the same line of text. However, a shorter and less tedious alternative is to add the string "\n" (newline) to the end of each line written to the file, like this:
out.write("/*\n");
out.write(name + "\n");
//etc.
If you choose to do it this way and it ends up writing all the text to a single line anyway (a common problem if you're running Windows), use "\r\n" instead of just "\n".
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Java - Using Jena APi - Get data from RDF file
I'm using Java and Jena API.
I have the class Person with the datatype properties hasFirstName, hasLastName, hasDateOfBirth, hasGender.
Here is how one person is represented in my RDF file.
<rdf:Description rdf:about="http://www.fam.com/FAM#Bruno04/02/1980 ">
<j.0:FAMhasGender>H</j.0:FAMhasGender>
<j.0:FAMhasDateOfBirth>04/02/1980</j.0:FAMhasDateOfBirth>
<j.0:FAMhasLastName>DS </j.0:FAMhasLastName>
<j.0:FAMhasFirstName> Bruno</j.0:FAMhasFirstName>
</rdf:Description>
I'd like to get for each person the firstname, gender, date of birth and write that information in a text file. The problem I have is that it only writes the first woman/man he finds in the rdf file, but there is more than one woman and man.
Can you please explain me how can I solve this?
Thank you very much.
ExtendedIterator instances = onto.person.listInstances();
Individual instance = null;
Individual firstInstance = null;
while (instances.hasNext()) {
instance = (Individual) instances.next();
gen = instance.getPropertyValue(onto.hasGender).toString();
fname = instance.getPropertyValue(onto.hasFirstName).toString();
dd = instance.getPropertyValue(onto.hasDateOfBirth).toString();
writeFile(fname, dd, genr);}
// Write text file
public void writeFile(String fn, String dbir, String gn) {
String fileout = "D:/file1.txt";
String firstName = fn;
String dateB = dbir;
String gender = gn;
BufferedWriter out;
try {
out = new BufferedWriter(new FileWriter(fileout, true));
if (gender.equals("F")) {
out.write("[label= \"" + firstName + " \"\n\n\"D.Naiss:" + dnai1 + "\", " + shape + "]");
} else if (gender.equals("M")) {
out.write("[label= \"" + firstName + " \"\n\n\"D.Naiss:" + dnai1 + "\", " + shape2 + "]");
}
out.newLine();
// flushes and closes the stream
out.close();
} catch (IOException e) {
System.out.println("There was a problem:" + e);
}
}
Your problem has nothing to do with Jena or RDF but is rather a logic error in your coding.
You call writeFile() inside your while loop which opens a new file, writes the current entry and closes the file. So you are repeatedly overwriting your file with a single entry at one time so you will only ever end up with a single person in the file.
You need to refactor the code to open the file once before the while loop, have the writeFile() method simply add to that file (and not close it) and then close the file after the while loop.
Also as #Udo Kilmaschewski pointed out in your apparent duplicate the genr variable is not defined in the code you showed so you don't appear to be correctly passing the gender from your while loop to the writeFile() function.