I've finished my assignment (messily) and it works well enough in the uni linux computers - but I can't make file input work at home under XP. I wouldn't have thought that the windows/linux change would make a difference with the JRE...

(But then I'm new to this "com-puuuu-tah" stuff)

the directory contains:
ClassID.class & .java
ClassRecord.class & .java
RunRecord.class & .java
rec

rec is the file I'm trying to load.

IOException returned is:
(The filename, directory name, or volume label syntax is incorrect)

The section of code that deals with file io is here:

public ClassRecord(String filename) 
//load from file 
{ 
FileInputStream fis; 
InputStreamReader isr; 
...
try { 
 fis = new FileInputStream(filename); 
 isr = new InputStreamReader(fis); 
 ...
  } 
 } 
catch( IOException e) 
 { 
 System.out.println("LOADING ERROR! " + filename + "\n" + e); 
 } 
}

The complete code is below:
(If anybody needs to know what the task actually was I can put that in, but I don't think it's nessisary. Nor really is the complete code... but just in case.)

ClassID

import java.io.*; 
import java.util.*; 

public class ClassID 
{ 
/*feilds*/ 
private String strName; 
private int intID; 
private int intACN; 
private double dblTTim; //military H.MM 
private int intTMod; 
/*defaults*/ 
public String dftName = new String("[UNNAMED!]"); 
public int dftID = 0; 
public int dftACN = 0; 
public double dftTTim = 0.00; 
public int dftTMod = 0; 

/*CONSTRUCTORS*/ 
public ClassID() 
{ 
strName = new String(dftName); 
intID = dftID; 
intACN = dftACN; 
dblTTim = dftTTim; 
intTMod = dftTMod; 
} 
public ClassID(String inName, int inID, int inACN, double inTTim, int 
inTMod) 
//Alternate 
{ 
strName = new String(inName); 
intID = inID; 
intACN = inACN; 
dblTTim = inTTim; 
intTMod = inTMod; 
} 
public ClassID(String inString) 
//Alternate2 - 1 
{ 
StringTokenizer sttTokStr; 
sttTokStr = new StringTokenizer(inString); 
if (sttTokStr.hasMoreTokens()) 
strName = new String(sttTokStr.nextToken()); 
else strName = new String(dftName); 
if (sttTokStr.hasMoreTokens()) 
intID = Integer.parseInt( sttTokStr.nextToken()); 
else intID = dftID; 
if (sttTokStr.hasMoreTokens()) 
intACN = Integer.parseInt( sttTokStr.nextToken()); 
else intACN = dftACN; 
if (sttTokStr.hasMoreTokens()) 
dblTTim = Double.parseDouble( sttTokStr.nextToken()); 
else dblTTim = dftTTim; 
if (sttTokStr.hasMoreTokens()) 
intTMod = Integer.parseInt( sttTokStr.nextToken()); 
else intTMod = dftTMod; 

System.out.println(toString()); 
} 
public ClassID(ClassID inID) 
//Alternate2 - 2 COPY 
{ 
strName = new String(inID.getName()); 
intID = inID.getID(); 
intACN = inID.getACN(); 
dblTTim = inID.getTTim(); 
intTMod = inID.getTMod(); 
} 
/*MUTATORS*/ 
//currently no validation. 
public void setName(String inName) 
{ 
strName = inName; 
} 
public void setID(int inID) 
{ 
intID = inID; 
} 
public void setACN(int inACN) 
{ 
intACN = inACN; 
} 
public void setTTim(double inTTim) 
{ 
dblTTim = inTTim; 
} 
public void setTMod(int inTMod) 
{ 
intTMod = inTMod; 
} 

/*ACCESSORS*/ 
public String getName() 
{ 
return new String(strName); 
} 
public int getID() 
{ 
return intID; 
} 
public int getACN() 
{ 
return intACN; 
} 
public double getTTim() 
{ 
return dblTTim; 
} 
public int getTMod() 
{ 
return intTMod; 
} 
public String toString() 
/*Format: (space seperated.) 
strName intID intACN dblTTim intTMod*/ 
{ 
String strTMod = new String("No mode specified"); 
if( intTMod == 0) 
strTMod = "ENTRY"; 
else if( intTMod == 1) 
strTMod = "EXIT"; 
return new String(strName + " " + intID + " " + intACN + " " +dblTTim + " " 
+ strTMod); 
} 
public String saveString() 
{ 
return new String(strName + " " + intID + " " + intACN + " " +dblTTim + " " 
+ intTMod + ":"); 
} 
public boolean equals(ClassID id2) 
//compares id number and name. 
//case sensitive 
{ 
boolean sfgrdgkj = false; 
if( strName.equals(id2.getName()) && intID == id2.getID()) 
sfgrdgkj = true; 
return sfgrdgkj; 
} 
}

ClassRecord

import java.io.*; 
import java.util.*; 
public class ClassRecord 
/* 
+constructors... 
... 
+toString 
+save 
+add 
+getLength 
+getCidValue 
+findByID 
+findByName 
*/ 
{ 
private ClassID cid[]; 

public ClassRecord(String filename) 
//load from file 
{ 
FileInputStream fis; 
InputStreamReader isr; 
int data; 
String str = new String(); 
try { 
fis = new FileInputStream(filename); 
isr = new InputStreamReader(fis); 
data = isr.read(); 
double dblN = 0.0; 
double d = 0.1; 
int n = 0; 
while( data != (int)':') 
{ 
dblN += d*(double)(data - 48); //48 is 0 code. 
data = isr.read(); 
d = d/10.0; 
} 
n = (int)(dblN/(d*10.0)); 
System.out.println("number of entries= " + n); 
cid = new ClassID [n]; 
data = isr.read(); //skip the : 
data = isr.read(); 
int i = 0; 
while(i<n) 
{ 
while( data != -1 && data != (int)':') 
{ 
str += (char)data; 
data = isr.read(); 
} 
cid[i] = new ClassID(str); 
data = isr.read(); //skip : 
data = isr.read(); 
str = ""; 
i++; 
} 
} 
catch( IOException e) 
{ 
System.out.println("LOADING ERROR! " + filename + "\n" + e); 
} 
} 
public ClassRecord(ClassRecord inRec) 
{ 
cid = new ClassID[inRec.getLength()]; 
for( int i=0; i<inRec.getLength(); i++) 
cid[i] = new ClassID(inRec.getCidValue(i)); 
} 
public ClassRecord(int n) 
//constructs an array of size n default elements 
{ 
cid = new ClassID[n]; 
for( int i=0; i<n; i++) 
cid[i] = new ClassID(); 
} 
public void save(String filename) 
//write to file 
{ 
FileOutputStream fos; 
PrintWriter pw; 
try { 
System.out.println("SAVING... " + filename); 
fos = new FileOutputStream(filename); 
pw = new PrintWriter(fos, true); 
pw.println(cid.length + ":"); 
for( int i = 0; i< cid.length; i++) 
pw.println(cid[i].saveString()); 
pw.close(); 
System.out.println("DONE SAVING!"); 
} 
catch (IOException e) 
{ 
System.out.println("WRITE ERROR! " + filename); 
} 
} 
public void add(ClassID inID) 
//add one elment on end 
{ 
int m = cid.length; 
int n = m+1; 
ClassID cid2[]; 
cid2 = new ClassID[m]; 
for( int i=0; i<m;i++) 
cid2[i] = new ClassID(cid[i]); 
cid = new ClassID [n]; 
for( int i=0; i<m; i++) 
{ 
cid[i] = new ClassID(cid2[i]); 
} 
cid[m] = new ClassID(inID); 
} 
public void findByName(String search) 
{ 
System.out.println("SEARCHING for: " + search + 
"\n#.| Name | ID | ACN | time(military) | mode"); 
int resultCount = 0; 
for( int i=0; i< cid.length; i++) 
{ 
if ((cid[i].getName()).equals(search)) 
{ 
resultCount++; 
System.out.println(i + ". " + cid[i].toString()); 
} 
} 
System.out.println("The Search is COMPLETE.\n" + 
resultCount + " result(s) found matching your request."); 
} 
public void findByID(int search) 
{ 
System.out.println("SEARCHING for: " + search); 
int resultCount = 0; 
for( int i=0; i< cid.length; i++) 
{ 
if (cid[i].getID() == search) 
{ 
resultCount++; 
System.out.println(i + ". " + cid[i].toString()); 
} 
} 
System.out.println("The Search is COMPLETE.\n" + 
resultCount + " result(s) found matching your request."); 
} 
public int getLength() 
{ 
return cid.length; 
} 
public ClassID getCidValue(int i) 
{ 
return new ClassID(cid[i]); 
} 
public String toString() 
//for displaying results only 
{ 
String outString = new String(""); 
int n = cid.length; 
for( int i=0; i<n; i++) 
outString += (i+1) + ". " + cid[i].toString() + "\n"; 
return outString; 
} 
public int getNumPpl() 
//finds number of different people in the current array 
//uses ClassID equals() 
{ 
/* 
ppl = 1 
FOR c = 1 to n-1 
if beenBefore(c) returns false 
then increment ppl 
END FOR 
*/ 
int n = cid.length; 
int i = 0; 
int ppl = 1; //num people so far, including 0th element. 
for( int c=1; c<n; c++) 
{ 
if(beenBefore(c) == false) 
ppl++; //ie, if there have been none the same so far, 
//then increment ppl. 
} 
return ppl; 
} 
public boolean beenBefore(int c) 
//has this person been in a previous ClassID? 
{ 
boolean equ = false; 
int n = cid.length; 
int i = 0; 
i = 0; 
while((i<c) && (equ == false)) 
{ 
if( cid[i].equals(cid[c])) 
equ = true; 
i++; 
} 
return equ; 
} 
public void groupID() 
{ 
save("rtemp"); 
ClassRecord rtemp = new ClassRecord("rtemp"); 
int ct = 0; 
int it = 0; 
int cc = 0; 
int ic = 0; 
while(ct<cid.length) 
{ 
if(rtemp.beenBefore(ct) == false) 
{ 
cid[cc] = new ClassID(rtemp.getCidValue(ct)); cc++; 
for(it=ct+1;it<cid.length;it++) 
{ 
if((rtemp.getCidValue(it)).equals(cid[(cc-1)])) 
{ 
cid[cc] = new ClassID(rtemp.getCidValue(it)); cc++; 
} 
} 
} 
ct++; 
} 

/* 
WHILE ct<n 
IF t(ct) beenbefore = false 
THEN 
c(cc) = t(ct) 
cc++ 
FOR (ct<it<n) 
IF t(it) = c(ct-1) 
THEN 
c(cc) = t(it) 
cc++ 
END IF 
END FOR 
END IF 
ct++ 
END WHILE 

Run Example: 
FROM: 
Alexander 1 1 6.0 ENTRY 
Birchcoff 2 1 7.0 ENTRY 
Cronowijk 3 2 7.01 ENTRY 
Dawson 4 3 7.23 ENTRY 
Eden 5 2 8.3 ENTRY 
Cronowijk 3 2 8.31 EXIT 
Alexander 1 1 9.0 EXIT 
Birchcoff 2 1 9.1 EXIT 
Dawson 4 3 9.11 EXIT 
Eden 5 2 9.12 EXIT 


TO: 
1. Alexander 1 1 6.0 ENTRY 
2. Alexander 1 1 9.0 EXIT 
3. Birchcoff 2 1 7.0 ENTRY 
4. Birchcoff 2 1 9.1 EXIT 
5. Cronowijk 3 2 7.01 ENTRY 
6. Cronowijk 3 2 8.31 EXIT 
7. Dawson 4 3 7.23 ENTRY 
8. Dawson 4 3 9.11 EXIT 
9. Eden 5 2 8.3 ENTRY 
10. Eden 5 2 9.12 EXIT 


*/ 
} 
public void viewDurations() 
{ 
int imin, imax; 
groupID(); 
int c = 0; 
int k = 0; 
String strDur[]; 
strDur = new String[getNumPpl()]; 
while( c<cid.length) 
{ 
imin = c; 
//while the next element has the same person as this one 
if( c+1<cid.length) 
if( cid[c+1].equals(cid[c])) 
c++; 
imax = c; 
strDur[k] = new String(calcTotalTime(imin, imax) + ": " + 
cid[c].getID() + " " + cid[c].getName()); 
k++; c++; 
} 
//SORT BY THE durations - not coded 
System.out.println("_______________________________" + 
"\nduration | ID | Name\n"+ 
"[-ve duration: worker did not leave]"); 
for(k=0;k<getNumPpl();k++) 
System.out.println(strDur[k]); 
/* 
sort, if things are same, calcTotalTime(imin, imax), 
stick stuff in an array of strings or make some other object, 
then sort them into the correct order. 
*/ 
} 
private double calcTotalTime(int imin, int imax) 
{ 
/* 
IMPORTS: - 
EXPORTS: total (a double) 
double total = 0.0 
FOR (imin <= i <= imax) 
IF cid[i].getTMod() = 0 
THEN total = total - cid[i].getTTim() 
ELSE total += cid[i].getTTim() 
END FOR 
*/ 
int hours = 0; 
int mins = 0; 
int t = 0; 
for( int i = imin; i<=imax; i++) 
{ 
t = (int)(100.00*cid[i].getTTim()); 
System.out.println(cid[i].getTTim()); 
if(cid[i].getTMod() == 0) 
{ 
hours = hours - t/100; 
mins = mins - (t%100); 
} 
else 
{ 
hours += t/100; 
mins += t%100; 
} 
} 
hours += mins/60; //note: integer division. 
mins = mins - 60*(mins/60); // note: integer division. 
if( mins<0) 
{ 
mins = mins+60; 
hours = hours -1; 
} 
return ((double)hours + ((double)(mins))/100.0); 
/* 
ASSERTION - data is valid. 
Valid data: 
is in pairs of 01! starts on 0, ends with 1, 
0 never follows 0 and 1 never follows 0, 
and only 0 and 1 are present. 

Run Example: 
from: 
Name/ID/ACN/Time(H.MM)/mode 
1. Alexander 1 1 6.0 ENTRY 
2. Alexander 1 1 9.0 EXIT 
3. Birchcoff 2 1 7.0 ENTRY 
4. Birchcoff 2 1 9.1 EXIT 
5. Cronowijk 3 2 7.01 ENTRY 
6. Cronowijk 3 2 8.31 EXIT 
7. Dawson 4 3 7.23 ENTRY 
8. Dawson 4 3 9.11 EXIT 
9. Eden 5 2 8.3 ENTRY 
10. Eden 5 2 9.12 EXIT 
11. Henderson 6 3 0.1 ENTRY 
12. Henderson 6 4 1.0 EXIT 
13. Joans 7 5 9.0 ENTRY 
14. Mapel 8 3 9.0 ENTRY 
15. Mapel 8 3 9.01 EXIT 
16. Jhonston 9 2 6.0 ENTRY 
to: 
duration | ID | Name 
[-ve duration: worker did not leave] 
3.0: 1 Alexander 
2.1: 2 Birchcoff 
1.3: 3 Cronowijk 
1.48: 4 Dawson 
0.41: 5 Eden 
0.5: 6 Henderson 
-9.0: 7 Joans 
0.01: 8 Mapel 
-6.0: 9 Jhonston 
*/ 
} 
}

RunRecord

import io.*; 
import java.io.*; 

public class RunRecord 
{ 
public static void main( String []args) 
{ 
String filename = new String(ConsoleInput.readLine( 
"Please Enter filename to load/prep\n" + 
"[a non-existant file will go to main menu]")); 
ClassRecord rec = new ClassRecord(filename); 

boolean timeToBuggerOff = false; 
do { 
System.out.println("_______________________________" + 
"\nSECURITY RECORD - MAIN MENU\n" + 
"Apparent file: " + filename + "\n" + 
"1 - LOAD a new file\n" + 
"2 - SAVE changes OVER " + filename + "\n" + 
"3 - SAVE AS\n" + 
"4 - ADD a new entry\n" + 
"5 - SEARCH for an entry\n" + 
"6 - VEIW current file\n" + 
"7 - VEIW sign in durations\n" + "8 - QUIT"); 
int choice = ConsoleInput.readInt( 
"Please enter your selection and press ENTER"); 
if (choice == 1) 
{ 
filename = ConsoleInput.readLine( 
"Please Enter filename"); 
rec = new ClassRecord(filename); 
} 
else if (choice == 2) 
rec.save(filename); 
else if (choice == 3) 
{ 
filename = ConsoleInput.readLine( 
"Please Enter filename"); 
rec.save(filename); 
} 
else if (choice == 4) 
{ 
System.out.println("NEW ENTRY:"); 
rec.add(new ClassID(ConsoleInput.readLine("Name") + 
" " + ConsoleInput.readLine("ID") + 
" " + ConsoleInput.readLine("Access Control Number (ACN)") + 
" " + ConsoleInput.readLine("time (in the form HH.MM, otherwise [Deleted For Security Reasons] you do wrong.)") + 
" " + ConsoleInput.readLine("Mode:\n0.Entry\n1.Exit\n (enter number only. See above.)"))); 
} 
else if (choice == 5) 
{ 
int choice2 = ConsoleInput.readInt( 
"Search by:\n1.Name\n2.ID number\nENTER NUMBER ONLY"); 
if (choice2 == 1) 
rec.findByName(ConsoleInput.readLine("Enter Name")); 
else 
rec.findByID(ConsoleInput.readInt("Enter ID")); 
} 
else if (choice == 6) 
{ 
System.out.println("_______________________________\n" + 
"Name/ID/ACN/Time(H.MM)/mode\n" + rec.toString()); 
} 
else if (choice == 8) 
timeToBuggerOff = true; 
else if (choice == 7) 
{ 
rec.viewDurations(); 
} 
else 
System.out.println("Invalid entry."); 
} 
while (timeToBuggerOff == false); 
} 
}

rec
16:
Alexander 1 1 6.0 0:
Birchcoff 2 1 7.0 0:
Henderson 6 3 0.1 0:
Mapel 8 3 9.01 1:
Jhonston 9 2 6.0 0:
Cronowijk 3 2 8.31 1:
Eden 5 2 9.12 1:
Dawson 4 3 9.11 1:
Eden 5 2 8.3 0:
Alexander 1 1 9.0 1:
Henderson 6 4 1.0 1:
Joans 7 5 9.90 0:
Dawson 4 3 7.23 0:
Birchcoff 2 1 9.1 1:
Cronowijk 3 2 7.01 0:
Mapel 8 3 9.0 0:

Error you get is: "IOException returned is:
(The filename, directory name, or volume label syntax is incorrect)"
Did you check if you're giving the path correctly? May be it's some simple bug like using "/" instead of "\" (/ is for Linux/Unix and \ for windows as you know)

Error you get is: "IOException returned is:
(The filename, directory name, or volume label syntax is incorrect)"
Did you check if you're giving the path correctly? May be it's some simple bug like using "/" instead of "\" (/ is for Linux/Unix and \ for windows as you know)

Just as a note. You can use "/" in Java on both Windows and all Unix flavors (I haven't got a Mac to try, but I'm fairly sure you can use it there, too). So, for convenience sake (and efficiency sake, since it will eliminate errors such as using a single, instead of a double, "\") it is better to either always use "/", or, if you don't like this, to always use File.separator

@masijade:
Interesting..
Checked and it works as well.. :)

@Zatnik
Can you please post the full stack trace that you got.. ?

stack trace? Unfortunatly I'm new to this, so I don't actually know what that is. (and "a printout of the calling stack with the current routine at the top of the trace, showing the name of any violated assertions," doesn't mean much to me. Sorry.)

With the linix computers I didn't need to use a path - just "rec" worked, I'm guessing since "rec" is in the directory I'm running my program from - I find I can load rec if I recompile with the path inside the program itself,

//fis = new FileInputStream(filename); 
fis = new FileInputStream("C:\\Documents and Settings\\Step\\My Documents\\Curtin\\2007-Sem1\\ST152\\W01\\rec");

but that rather defies the point of trying to load and save different files by typing them into the command line. I suppose I could always put ("C:\\Documents and Settings\\Step\\My Documents\\Curtin\\2007-Sem1\\ST152\\W01\\" + filename), but then (if I made something similar and wanted to use it on different computers) I'de have to recompile it with whatever path every single tmie.

But possibly I'm working towards my own solution: is there something I can put into the code that will just mean "this current directory here"?
Also, how would I got about typing the path into the command line.

Oh, on testing, ("C:\\Documents and Settings\\Step\\My Documents\\Curtin\\2007-Sem1\\ST152\\W01\\" + filename) doesn't work, though ("C:\\Documents and Settings\\Step\\My Documents\\Curtin\\2007-Sem1\\ST152\\W01\\rec") does. I have no idea why.

(thanks for looknig at this.)

I will go out on a limb and say that the problem arises form the following:

filename = ConsoleInput.readLine( "Please Enter filename");
rec.save(filename);

As I am fairly sure that you will be entering the filename as follows:

C:\Bogus\Path\To\File.txt

if this is the case you need to modify the above two lines as follows:

filename = ConsoleInput.readLine( "Please Enter filename");
rec.save(filename.replaceAll("\\", "\\\\"));
// or rec.save(filename.replaceAll("\\", "/"));

As otherwise, you are saving a String with single "\" characters in it, and so, when you attempt to open the file it will interpret the "\" and the character directly after it as special constructs, so you need to escape each of those single "\" characters with a double "\" character, but since "\" is a special character in the replace Strings, you need to escape it there as well, which is the reason for the double and then quadruple "\" characters in the replace statement. The double "\" will find all instances of a "\" and the quadruple "\" will place a double "\" in all those places.

I hope this makes sense to you, as I can't really explain it any better.

In other words:
You need to understand how the escape characters/sequences work in Java. When you prefix a character in a string with a '\' you are escaping it. When you escape a character it's meaning changes as masijade explained..
Finally abt the stack trace.. In your code replace:

catch( IOException e)
{
    System.out.println("LOADING ERROR! " + filename + "\n" + e);
}

with

catch( IOException e)
{
    System.out.println("IOException caught. Stack trace is:");
    e.printStackTrace();
}

Now run your program with the wrong path and see what is printed on the screen. That's your stack trace.

This article has been dead for over six months. Start a new discussion instead.