I'm making a client/server program for a computer science class.
The idea is that we have a server program that takes a list of console commands, performs them, and returns a response via Input / Output streams. Because of the formatting of the commands, I have to check for whitespaces and digits and split the strings accordingly (which I've done). The problem appears to be in the retrieval of the command from the InputStream.
Commands that should be accepted:
put [string] [int]
- this should store a string (key) and int (value) in the HashMap
get [string]
- this should return the int associated with this string
keyset
- return all keys
values
- return all values
mappings
- return all mappings
bye
- quit the client
help
- doesn't do anything yet, but will list all commands and their syntax
The professor gave us much of the code for the server, but I think there may be errors in it because I keep getting exceptions on the Scanner. See server code below:
package mapserver;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
public class MapServer
{
public static void main(String[] args) throws IOException
{
ServerSocket serverSocket = new ServerSocket(50000);
while (true)
{
Socket activeSock = serverSocket.accept();
Thread th = new Thread(new MapServerThread(activeSock));
th.start();
}
}
}
class MapServerThread implements Runnable
{
private Map<String, Integer> map = new HashMap<>();
private Socket sock;
public MapServerThread(Socket s)
{
sock = s;
List<String> strs = Arrays.asList("aaa a", "b", "a");
for (String str : strs)
{
map.put(str, str.length());
}
}
#Override
public void run()
{
try
{
InputStream in = sock.getInputStream();
OutputStream out = sock.getOutputStream();
BufferedReader reader =
new BufferedReader(new InputStreamReader(in));
PrintWriter writer = new PrintWriter(out, true);
// welcome message
writer.println("Welcome to the map service.");
String inputLine = null;
while ((inputLine = reader.readLine()) != null)
{
Scanner sc = new Scanner(inputLine);
String fullLine =
sc.nextLine().toLowerCase().trim().replaceAll("\\s+", " ");
writer.println(fullLine);
int cmdLoc = 0;
for (int k = 0; k <fullLine.length(); k++)
{
if (fullLine.charAt(k)==' ');
{
cmdLoc = k;
}
}
String cmd;
if (cmdLoc == 0)
{
cmd = fullLine;
writer.println(cmd);
}
else
{
cmd = fullLine.substring(0, cmdLoc+1);
writer.println(cmd);
}
int startloc = cmd.length() + 1;
switch(cmd)
{
case "put":
int intlocation = startloc;
for (int k = 0; k < fullLine.length(); k++)
{
if (Character.isDigit(fullLine.charAt(k)))
{
intlocation = k;
}
}
// if the int is located at the beginning, the format
// is wrong. Let the user know
if (intlocation == startloc)
{
writer.println("Invalid entry. Correct format "
+ "is \"put <string> <integer>\"");
}
// Split the user's entry for putting
else
{
String stringToPut =
fullLine.substring(startloc, intlocation+1);
int intToPut =
Integer.parseInt(fullLine.substring(intlocation));
map.put(stringToPut, intToPut);
writer.println("Ok!");
}
continue;
case "get":
int returnvalue =
map.get(fullLine.substring(startloc));
writer.println(returnvalue);
continue;
case "keyset":
String result = map.keySet().toString();
writer.println(result);
continue;
case "values" :
String result1 = map.values().toString();
writer.println(result1);
continue;
case "mappings" :
writer.println(map.size());
map.forEach(
(k, v) ->
{ writer.println( k + " " + v);}
);
continue;
case "bye" :
writer.println("See you later.");
sock.shutdownOutput();
sock.close();
return;
case "help" :
continue;
default :
writer.println("Not a recognized command");
}
}
} catch (IOException ex)
{
throw new RuntimeException(ex);
}
}
}
I'm almost 100% sure the problem is in the server program, as I've been testing it with Telnet. I've tried using the BufferedReader directly instead of the scanner, but the server appears to be getting blank strings. Does anyone have any ideas? I've been fiddling with it for a couple of hours now and I just can't figure it out.
The Problem in a nutshell:
After I login, the server throws:
Exception in thread "Thread-0" java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Scanner.java:1540)
at mapserver.MapServerThread.run(MapServer.java:67)
at java.lang.Thread.run(Thread.java:745)
and I can't figure out why. If i don't use the scanner, for some reason the server is receiving blank input, regardless of what i type.
Here's what the correct interaction should look like:
Welcome to the MapService Client
Enter the IP address of the server: localhost
Please wait while I connect you...
Welcome to the map service.
Map service>mappings
3
a 1
b 1
aaa a 5
Map service>put North Central College 2014
Ok.
Map service>keyset
[a, b, aaa a, North Central College]
Map service>get North Central College
2014
Map service>help
7
help
get key
put key value
values
keyset
mappings
bye
Map service>values
[1, 1, 5, 2014]
Map service>bye
See you later.
Your code is broken, because it's trying to parse the same line twice:
String inputLine = null;
while ((inputLine = reader.readLine()) != null) //#1
//...
String fullLine =sc.nextLine().toLowerCase().trim().replaceAll("\\s+", " ");//#2
You can fix that particular piece with:
String fullLine =inputLine.toLowerCase().trim().replaceAll("\\s+", " ");
If you receive a blank inputLine for whatever reason, you can skip it with:
if(inputLine.trim().size()==0){
continue;//invokes the next loop iteration
}
EDIT:
I rewrote the class and tried to split up the parts to make it easier to grasp. Please give a feedback even though you marked it resolved:
class MapServerThread implements Runnable {
private enum Commands {
PUT("(put)\\s(\\S+)\\s(\\d)"),
//add all your commands here and give an approriate regular expression
UNKNOWN(".+");
private final String pattern;
Commands(String regexPattern) {
pattern = regexPattern;
}
private static Commands parseCommand(String s) {
Commands result = UNKNOWN;
s = s.toLowerCase(Locale.getDefault());
for (Commands command : values()) {
if (command != UNKNOWN && command.pattern.matches(s)) {
result = command;
break;
}
}
return result;
}
}
private Map<String, Integer> map = new HashMap<>();
private Socket sock;
public MapServerThread(Socket s) {
sock = s;
List<String> strs = Arrays.asList("aaa a", "b", "a");
for (String str : strs) {
map.put(str, str.length());
}
}
#Override
public void run() {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(sock.getInputStream()));
PrintWriter writer = new PrintWriter(sock.getOutputStream(), true);
writer.println("Welcome to the map service.");
String inputLine = null;
while ((inputLine = reader.readLine().trim()) != null) {
Commands command = Commands.parseCommand(inputLine);
writer.println(command.name());
execute(command, inputLine);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void execute(Commands command, String inputLine) {
switch (command) {
case PUT:
String[] args = inputLine.split(" ");
map.put(args[1], Integer.parseInt(args[2]));
break;
//handle the other commands accordingly
default:
// notify about an error
break;
//
// get [string] - this should return the int associated with this string
//
// keyset - return all keys
//
// values - return all values
//
// mappings - return all mappings
//
// bye - quit the client
//
// help - doesn't do anything yet, but will list all commands and their
// syntax
}
}
}
Related
I've been searching the web and I can't seem to find a working solution.
I have a file containing theses lines:
Room 1
Coffee
Iron
Microwave
Room_end
Room 2
Coffee
Iron
Room_end
I want to print all Strings between Room 1 and Room_end. I want my code to start when it find Room 1, print line after Room 1 and stop when it get to the first Room_end it find.
private static String LoadRoom(String fileName) {
List<String> result = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
result = reader.lines()
.dropWhile(line -> !line.equals("Room 1"))
.skip(1)
.takeWhile(line -> !line.equals("Room_end"))
.collect(Collectors.toList());
} catch (IOException ie) {
System.out.println("Unable to create " + fileName + ": " + ie.getMessage());
ie.printStackTrace();
}
for (int i = 0; i < result.size(); i++) {
System.out.println(result.get(i).getname());//error on getname because it cant work with Strings
}
}
class Model {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I am able to get a method to print all Strings of the file but not specific range of Strings. I also tried to work with Stream. My code feel quite messy, but I've been working on it for a while an it seems it only get messier.
I think there is a problem if you want to use lambda expression here:
lambda expressions are functional programming, and functional programming requires immutability, that means there should not be state related issue, you can call the function and give it same parameters and the result always will be the same, but in your case, there should be a state indicating whether you should print the line or not.
can you try this solution? I write it in python, but mainly it is just about a variable should_print that located outside of the scope
should_print = False
result = reader.lines()
for line in result:
if line == "Room end":
break
if should_print:
print(line)
if line == "Room 1":
should_print = True
keep a boolean value outside of the iteration, and check/update the value in each iteration
public static Map<String, List<String>> getRooms(String path) throws IOException {
Map<String, List<String>> result = new HashMap<>();
try (Scanner sc = new Scanner(new File(path))) {
sc.useDelimiter("(?=Room \\d+)|Room_end");
while (sc.hasNext()) {
Scanner lines = new Scanner(sc.next());
String room = lines.nextLine().trim();
List<String> roomFeatures = new ArrayList<>();
while (lines.hasNextLine()) {
roomFeatures.add(lines.nextLine());
}
if (room.length() > 0) {
result.put(room, roomFeatures);
}
}
}
return result;
}
is one way of doing it for your 'rooms file' though it should really be made more OO by making a Room bean to hold the data. Output with your file: {Room 2=[Coffee, Iron ], Room 1=[Coffee, Iron, Microwave]}
Switched my code and used this:
private static String loadRoom(String fileName) {
BufferedReader reader = null;
StringBuilder stringBuilder = new StringBuilder();
try {
reader = new BufferedReader(new FileReader(fileName));
String line = null; //we start with empty info
String ls = System.getProperty("line.separator"); //make a new line
while ((line = reader.readLine()) != null) { //consider if the line is empty or not
if (line.equals("Room 1")) { //condition start on the first line being "Room 1"
line = reader.readLine(); // read the next line, "Room 1" not added to stringBuilder
while (!line.equals("Room_end")) { //check if line String is "Room_end"
stringBuilder.append(line);//add line to stringBuilder
stringBuilder.append(ls);//Change Line in stringBuilder
line = reader.readLine();// read next line
}
}
}
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null)
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return stringBuilder.toString();
}
Here's a solution that uses a scanner and a flag. You may choose to break the loop when it reads "Room_end"
import java.util.Scanner;
import java.io.*;
public class Main{
private static String loadRoom(String fileName) throws IOException {
Scanner s = new Scanner(new File(fileName));
StringBuilder sb = new StringBuilder();
boolean print = false;
while(s.hasNextLine()){
String line = s.nextLine();
if (line.equals("Room 1")) print = true;
else if (line.equals("Room_end")) print = false;
else if (print) sb.append(line).append("\n");
}
return sb.toString();
}
public static void main(String[] args) {
try {
String content = loadRoom("content.txt");
System.out.println(content);
}catch(IOException e){
System.out.println(e.getMessage());
}
}
}
move keywords flagstop, wb, nb, sb, eb from start of the names to the end of the names
of the stops when reading the file
eg “WB HASTINGS ST FS HOLDOM AVE” becomes “HASTINGS ST FS HOLDOM AVE WB”.
So far I have gotten the code to read in the file as shown below, but im unsure how to move keyword of this string in array to end of string given the criteria shown above.
I need to be able to move first word in stops[2] if it is any of the above postcodes. Is there a way in JAVA to do this? Im thinking I need to make separate a function (moveFirstToLast) and call this in the main, but im having difficulty with this.
'''
String line = "";
try {
#SuppressWarnings("resource")
BufferedReader x = new BufferedReader(new FileReader("stops.txt"));
while((line = x.readLine()) != null)
{
String[] stops = line.split(",");
System.out.println("Stop name:" + stops[2]);
}
}
'''
Using a regex replacement:
String input = "WB HASTINGS ST FS HOLDOM AVE";
String output = input.replaceAll("(\\S+) (.*)$", "$2 $1");
System.out.println(output); // HASTINGS ST FS HOLDOM AVE WB
You can use String#split() to separate the first word from the rest of the string.
public moveFirstToLast(String stopName){
String [] temp = stopName.split(" ", 2);
return temp[1] + " " + temp[0];
}
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class Sample_Two {
public static void main(String[] args) {
String line = "";
try {
#SuppressWarnings("resource")
BufferedReader x = new BufferedReader(new FileReader("stops.txt"));
while ((line = x.readLine()) != null) {
System.out.println("Actual line===>" + line);
var arr = line.split("\\s");
if (arr != null && arr.length > 0) {
System.out.println("Updated line===>" + line.substring(line.indexOf(" ")) +" "+ arr[0]);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
You can try above code.
Why you are splitting through comma ",".
You need to split through space.
This will help you.
I have got two text files with data in the following format
data.txt file as following format
A 10
B 20
C 15
data1.txt file is in format (start node,end node, distance):
A B 5
A C 10
B C 20
I am trying to implement a search strategy, for that I need to load the data from data.txt and ONLY the start node and end node from data1.txt (i.e. I dont need the distance). I need to store this information in a stack as I think it would be a best data structure for implementing greedy search.
Actually I am not sure how to get started with file I/O to read these files and store them in array to implement greedy search. So I would highly appreciate any starting idea on how to proceed.
I am new to this, so please bear with me. Any help is much appreciated. Thanks.
EDIT:
Here is what I have got till now
String heuristic_file = "data.txt";
try
{
FileReader inputHeuristic = new FileReader(heuristic_file);
BufferedReader bufferReader = new BufferedReader(inputHeuristic);
String line;
while ((line = bufferReader.readLine()) != null)
{
System.out.println(line);
}
bufferReader.close();
} catch(Exception e) {
System.out.println("Error reading file " + e.getMessage());
}
My approach, doesn't differ fundamentally from the others. Please regard the try/catch/finally blocks. Always put the closing statements into the finally block, so the opened file is guaranteed to be closed, even if an exception was thrown while reading the file.
The part between the two //[...] could surely be done more efficient. Maybe reading the whole file in one take and then parsing the text backwards and searching for a line-break? Maybe a Stream-API supports to set the reading position. I honestly don't know. I didn't need that, up to now.
I chose to use the verbose initialization of the BufferedReader, because then you can specify the expected encoding of the file. In your case it doesn't matter, since your files do not contain symbols out of the standard ASCII range, but I believe it's a semi-best-practice.
Before you ask: r.close() takes care of closing the underlying InputStreamReader and FileInputStream in the right order, till all readers and streams are closed.
public static void readDataFile(String dir, String file1, String file2)
throws IOException
{
File datafile1 = new File(dir, file1);
File datafile2 = new File(dir, file2);
if (datafile1.exists())
{
BufferedReader r = null;
try
{
r = new BufferedReader(
new InputStreamReader(
new FileInputStream(datafile1),
"UTF-8"
)
);
String row;
Stack<Object[]> s = new Stack<Object[]>();
String[] pair;
Integer datapoint;
while((row = r.readLine()) != null)
{
if (row != null && row.trim().length() > 0)
{
// You could use " " instead of "\\s"
// but the latter regular expression
// shorthand-character-class will
// split the row on tab-symbols, too
pair = row.split("\\s");
if (pair != null && pair.length == 2)
{
datapoint = null;
try
{
datapoint = Integer.parseInt(pair[1], 10);
}
catch(NumberFormatException f) { }
// Later you can validate datapairs
// by using
// if (s.pop()[1] != null)
s.add(new Object[] { pair[0], datapoint});
}
}
}
}
catch (UnsupportedEncodingException e1) { }
catch (FileNotFoundException e2) { }
catch (IOException e3) { }
finally
{
if (r != null) r.close();
}
}
// Do something similar with datafile2
if (datafile2.exists())
{
// [...do the same as in the first try/catch block...]
String firstrow = null, lastrow = null;
String row = null;
int i = 0;
do
{
lastrow = row;
row = r.readLine();
if (i == 0)
firstrow = row;
i++;
} while(row != null);
// [...parse firstrow and lastrow into a datastructure...]
}
}
use split
while ((line = bufferReader.readLine()) != null)
{
String[] tokens = line.split(" ");
System.out.println(line + " -> [" + tokens[0] + "]" + "[" + tokens[1] + "][" + tokens[2] + "]");
}
if you must have this in an array you can use the following:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
public class NodeTest {
public static void main(String[] args) throws ParseException {
try {
File first = new File("data.txt");
File second = new File("data1.txt");
Node[] nodes1 = getNodes(first);
Node[] nodes2 = getNodes(second);
print(nodes1);
print(nodes2);
}
catch(Exception e) {
System.out.println("Error reading file " + e.getMessage());
}
}
public static final void print(Node[] nodes) {
System.out.println("======================");
for(Node node : nodes) {
System.out.println(node);
}
System.out.println("======================");
}
public static final Node[] getNodes(File file) throws IOException {
FileReader inputHeuristic = new FileReader(file);
BufferedReader bufferReader = new BufferedReader(inputHeuristic);
String line;
List<Node> list = new ArrayList<Node>();
while ((line = bufferReader.readLine()) != null) {
String[] tokens = line.split(" ");
list.add(new Node(tokens[0], tokens[1]));
}
bufferReader.close();
return list.toArray(new Node[list.size()]);
}
}
class Node {
String start;
String end;
public Node(String start, String end){
this.start = start;
this.end = end;
}
public String toString() {
return "[" + start + "][" + end + "]";
}
}
Something like this?
HashSet<String> nodes = new HashSet<String>();
try(BufferedReader br = new BufferedReader(new FileReader("data.txt"))) {
String line = br.readLine();
while (line != null) {
String[] l = line.split(" ");
nodes.add(l[0]);
line = br.readLine();
}
}
try(BufferedReader br = new BufferedReader(new FileReader("data1.txt"))) {
String line = br.readLine();
while (line != null) {
String[] l = line.split(" ");
if (nodes.contains(l[0]) || nodes.contains(l[1]))
// Do whatever you want ...
line = br.readLine();
}
}
My assignment is as following Create Java program that reads from file create one person Object per line and stores object in a collection write the object out sorted by last name. this is what I have so far it compiles just fine but it doesn't print out anything. This is what I have so far
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class FileTester {
public static void main(String[] args) {
File testFile;
Scanner fileScanner;
try {
testFile = new File("sample.txt");
fileScanner = new Scanner(testFile);
fileScanner.useDelimiter(",");
while (fileScanner.hasNext()) {
System.out.println(fileScanner.next());
}
fileScanner.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
If it is a text file, please use BufferedReader. Then use String#split() to get the data. Instantiate as necessary.
BufferedReader reader = new BufferedReader(...);
String line = null;
while( (line = reader.readLine()) != null){
// magic
}
I do not know what you want to do. But this program take a file called "sample.txt" and divide in tokens this. For example if in the txt is "carlos,jose,herrera,matos" you program out
carlos
jose
herrera
matos
now if you want to sort this, you must create a class Person and implement the Comparable
Try this,
BufferedReader bufferedReader = new BufferedReader(new FileReader(new File(fileName)));
String content = null;
while((content = bufferedReader.readLine()) != null)
{
String[] details = content.split(",");
int i = 1;
for(String value : details)
{
switch(i)
{
case 1:
{
System.out.println("Name : "+value);
i=2;
break;
}
case 2:
{
System.out.println("Address : "+value);
i=3;
break;
}
case 3:
{
System.out.println("Number : "+value);
i = 1;
break;
}
}
}
}
I'm trying to write my java console output to a .txt file in my desktop.
But when that method starts, i have the console output and the txt file gets created, but it's empty and I realized that the BufferedReader (in) is not working... (Because of the "ok1 - i" statement)
The question is WHY?? or WHAT'S WRONG WITH MY CODE??
This is my code, so you can see and run it
package noobxd;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Random;
public class Main {
public static void main(String[] args) throws IOException {
String path = "C:\\Users\\Mario\\Desktop\\output.txt";
generate_codes();
writetxt(path);
}
private static void writetxt(String path) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter out = new BufferedWriter(new FileWriter(path));
try {
String inputLine;
inputLine = "";
int i=0;
System.out.println("Starting");
while (!inputLine.isEmpty()){
System.out.println("ok1"+i);
inputLine = in.readLine();
System.out.println("ok2"+i);
out.write(inputLine);
System.out.println("ok3"+i);
out.newLine();
System.out.println("ok4"+i);
i++;
}
System.out.print("Write Successful");
} catch (IOException e1) {
System.out.println("Error during reading/writing");
} finally {
out.close();
in.close();
}
}
private static void generate_codes() {
Random rnd = new Random();
for (int i = 0; i < 30; i++) {
int code = rnd.nextInt(201) + 100;
int students = rnd.nextInt(31) + 40;
int j = rnd.nextInt(4);
String type = new String();
switch (j) {
case 0:
type = "Theory";
break;
case 1:
type = "Lab";
break;
case 2:
type = "Practice";
break;
case 3:
type = "Exam";
break;
}
System.out.println("TEL" + code + "-TopicNumber" + i + "-" + students + "-" + type);
}
}
}
Thanks for your time, please help me solve my problem.
String inputLine;
inputLine = "";
...
while (!inputLine.isEmpty()) // this is false and so the loop is not executed
In the future, please learn to use debugging tools and simply read your code more carefully. If you're trying to read until EOF, use
while ((inputLine = in.readLine()) != null) {
...
}
If you want to keep looping until the user enters an empty line at the console, you probably want something like
while (true) {
System.out.println("ok1"+i);
inputLine = in.readLine();
if (inputLine.isEmpty())
break;
// the rest of your loop
}
You probable should do something like this:
inputLine = in.readLine();
while (inputLine != null && !inputLine.isEmpty()){
System.out.println("ok1"+i);
System.out.println("ok2"+i);
out.write(inputLine);
System.out.println("ok3"+i);
out.newLine();
System.out.println("ok4"+i);
i++;
inputLine = in.readLine();
}