4. Commonly Used Classes in the Java
In this chapter, we present a number of commonly used Java classes. These have numerous attributes, methods, and constructors. In each case, we present only a small portion of the classes. Details on these are available in the Java help, which we present now.
4.1. The documentation
If you have installed the Sun JDK in the <jdk> folder, the documentation is available in the <jdk>\docs folder:

Sometimes you have a JDK but no documentation. This can be found on Sun’s website at http://www.sun.com. In the docs folder, you’ll find an index.html file, which serves as the starting point for the JDK help:


The "API & Language" link above provides access to Java classes. The "Demos/Tutorials" link is particularly useful for finding examples of Java programs. Let's follow the "API & Language" link:

Let's follow the Java 2 Platform API link:

This page is the real starting point for the class documentation. You can create a shortcut to it for quick access. The URL is <jdk>\docs\api\index.html. It contains links to hundreds of Java classes in the JDK. When you’re just starting out, the main challenge is figuring out what these different classes do. Initially, this resource is only useful if you know the name of the class you want information about. You can also use the class names as a guide, as they usually indicate the class’s purpose.
Let’s take an example and look up information on the Vector class, which implements a dynamic array. Simply search the list of classes in the left pane for the Vector class link:

and click on the link to view the class definition:

There you will find
- the hierarchy in which the class is located, in this case java.util.Vector
- the list of fields (attributes) of the class
- the list of constructors
- the list of methods
In the following sections, we present various classes. We encourage the reader to systematically check the complete definition of the classes used.
4.2. Test classes
The following examples sometimes use the Person and Teacher classes. We provide their definitions here.
public class Person{
// last name, first name, age
private String firstName;
private String lastName;
private int age;
// constructor 1
public Person(String firstName, String lastName, int age) {
this.firstName = P;
this.lastName = N;
this.age = age;
}
// constructor 2
public Person(Person P) {
this.firstName = P.firstName;
this.lastName = P.lastName;
this.age = P.age;
}
// toString
public String toString(){
return "person(" + firstName + "," + lastName + "," + age + ")";
}
// accessors
public String getFirstName(){
return firstName;
}
public String getLastName(){
return lastName;
}
public int getAge(){
return age;
}
//accessors
public void setFirstName(String P){
this.firstName = P;
}
public void setLastName(String L){
this.lastName = N;
}
public void setAge(int age){
this.age = age;
}
}
The Teacher class is derived from the Person class and is defined as follows:
class Teacher extends Person {
// attributes
private int section;
// constructor
public Teacher(String P, String N, int age, int section) {
super(P, N, age);
this.section = section;
}
// toString
public String toString(){
return "student(" + super.toString() + "," + section + ")";
}
}
We will also use a student class derived from the person class and defined as follows:
class Student extends Person {
String id;
public Student(String P, String N, int age, String number) {
super(P, N, age);
this.number = number;
}
public String toString(){
return "student(" + super.toString() + "," + number + ")";
}
}
4.3. The String Class
The String class represents character strings. Let *name* be a character string variable:
*String name;*
name is a reference to an object that has not yet been initialized. It can be initialized in two ways:
**name = "horse"** or **name = new String("horse")**
Both methods are equivalent. If we later write name="fish", name then refers to a new object. The old String("horse") object is lost, and the memory it occupied will be reclaimed.
The String class has many attributes and methods. Here are a few:
public char charAt(int i) | returns the character at index i in the string, where the first character has index 0. Thus, `String("horse").charAt(3)` is equal to 'h' |
public int compareTo(string2) | string1.compareTo(string2) compares string1 to string2 and returns 0 if string1 = string2, 1 if string1 > string2, and -1 if string1 < string2 |
public boolean equals(Object anObject) | string1.equals(string2) returns true if string1 = string2, false otherwise |
public String toLowerCase() | string1.toLowerCase() converts string1 to lowercase |
public String toUpperCase() | string1.toUpperCase() converts string1 to uppercase |
public String trim() | string1.trim() removes leading and trailing spaces from string1 |
public String substring(int beginIndex, int endIndex) | String("chapeau").subString(2,4) returns the string "ape" |
public char[] toCharArray() | converts the characters of the string into a character array |
int length() | number of characters in the string |
int indexOf(String string2) | returns the first occurrence of string2 in the current string, or -1 if string2 is not present |
int indexOf(String string2, int startIndex) | Returns the first occurrence of string2 in the current string, or -1 if string2 is not found. The search starts at the character at position startIndex. |
int lastIndexOf(String string2) | Returns the last position of string2 in the current string, or -1 if string2 is not present |
boolean startsWith(String string2) | returns true if the current string begins with string2 |
boolean endsWith(String string2) | returns true if the current string ends with string2 |
boolean matches(String regex) | returns true if the current string matches the regular expression regex. |
String[] split(String regex) | The current string consists of fields separated by a string of characters matched by the regular expression regex. The split method retrieves the fields into an array. |
String replace(char oldChar, char newChar) | Replaces the character oldChar with the character newChar in the current string. |
Here is a sample program:
// imports
import java.io.*;
public class string1{
// a demonstration class
public static void main(String[] args){
String aString = "the bird flies above the clouds";
display("aString=" + aString);
display("aString.Length=" + aString.Length());
print("string[10]=" + string.charAt(10));
print("aString.IndexOf(\"flies\")=" + aString.indexOf("flies"));
print("string.IndexOf("x")=" + string.IndexOf("x"));
print("aString.LastIndexOf('a')=" + aString.lastIndexOf('a'));
print("aString.LastIndexOf('x')=" + aString.lastIndexOf('x'));
display("aString.substring(4,7)="+aString.substring(4,7));
display("aString.ToUpper()=" + aString.toUpperCase());
print("aString.ToLower()=" + aString.toLowerCase());
print("aString.Replace('a','A')=" + aString.replace('a','A'));
String[] fields = string.split("\\s+");
for (int i = 0; i < fields.length; i++) {
display("fields[" + i + "] = [" + fields[i] + "]");
}//for
display("(\" abc \").trim()=["+" abc ".trim()+"]");
}//Main
// display
public static void display(String msg){
// display msg
System.out.println(msg);
}//display
}//class
and the results obtained:
aString = "the bird flies above the clouds"
string.length = 34
string[10] = o
string.IndexOf("flies")=9
string.IndexOf("x")=-1
aString.LastIndexOf('a')=30
aString.LastIndexOf('x')=-1
aString.substring(4,7) = "sea"
aString.ToUpper() = THE BIRD FLIES ABOVE THE CLOUDS
aString.ToLower() = the bird flies above the clouds
uneChaine.Replace('a','A') = "The bird flies above the clouds"
champs[0] = [the bird]
fields[1] = [flies]
fields[2] = [above]
fields[3] = [the]
fields[4] = [clouds]
(" abc ").trim()=[abc]
4.4. The Vector Class
A vector is a dynamic array whose elements are object references. It is therefore an array of objects whose size can vary over time, which is not possible with the static arrays we have encountered so far. Here are some fields, constructors, or methods of this class:
public Vector() | constructs an empty vector |
public final int size() | number of elements in the vector |
public final void addElement(Object obj) | adds the object referenced by obj to the vector |
public final Object elementAt(int index) | reference to the object at index in the array - indices start at 0 |
public final Enumeration elements() | the set of elements in the array as an enumeration |
public final Object firstElement() | reference to the first element of the array |
public final Object lastElement() | reference to the last element of the vector |
public final boolean isEmpty() | returns true if the array is empty |
public final void removeElementAt(int index) | removes the element at index |
public final void removeAllElements() | clears the array of all its elements |
public final String toString() | returns a string representing the array |
Here is a test program:
// imported classes
import java.util.*;
public class test1{
// the main program main - static - class method
public static void main(String arg[]){
// Creating class instance objects
person p = new person("Jean", "Dupont", 30);
teacher en = new Teacher("Paula", "Hanson", 56, 27);
student student = new Student("Chris", "Garot", 22, "19980405");
System.out.println("p=" + p.toString());
System.out.println("en=" + en.toString());
System.out.println("student = " + student.toString());
// polymorphism
person p2 = (person) en;
System.out.println("p2=" + p2.toString());
person p3 = (person) and;
System.out.println("p3=" + p3.toString());
// a vector
Vector V = new Vector();
V.addElement(p); V.addElement(en); V.addElement(et);
System.out.println("Size of vector V = " + V.size());
for(int i=0;i<V.size();i++){
p2 = (Person) V.elementAt(i);
System.out.println("V[" + i + "] = " + p2.toString());
}
} // end of main
}// end class
Let's compile this program:
E:\data\serge\JAVA\poly June 2002\Chapter 3\vector>dir
06/10/2002 10:41 1,134 person.class
06/10/2002 10:41 619 teacher.class
06/10/2002 10:41 610 student.class
06/10/2002 10:42 1,035 test1.java
E:\data\serge\JAVA\poly June 2002\Chapter 3\vector>javac test1.java
E:\data\serge\JAVA\poly June 2002\Chapter 3\vector>dir
06/10/2002 10:41 1,134 person.class
06/10/2002 10:41 619 teacher.class
06/10/2002 10:41 610 student.class
06/10/2002 10:42 1,035 test1.java
06/10/2002 10:43 1,506 test1.class
Let's run the test1.class file:
E:\data\serge\JAVA\poly June 2002\Chapter 3\vector>java test1
p = person(Jean, Dupont, 30)
en=student(person(Paula,Hanson,56),27)
et=student(person(Chris,Garot,22),19980405)
p2 = student(person(Paula, Hanson, 56), 27)
p3 = student(person(Chris, Garot, 22), 19980405)
Size of vector V = 3
V[0] = person(Jean, Dupont, 30)
V[1] = student(person(Paula, Hanson, 56), 27)
V[2] = student(person(Chris, Garot, 22), 19980405)
From now on, we will no longer repeat the process of compiling and running the test programs. Simply repeat what was done above.
4.5. The ArrayList Class
The ArrayList class is analogous to the Vector class. It differs from it primarily only when used simultaneously by multiple threads. The thread synchronization methods for accessing a Vector or an ArrayList differ. Outside of this case, either one can be used interchangeably. Here are some fields, constructors, or methods of this class:
ArrayList() | constructs an empty array |
int size() | number of elements in the array |
void add(Object obj) | adds the object referenced by obj to the array |
void add(int index, Object obj) | adds the object referenced by obj to the array at position index |
Object get(int index) | reference to the object at index in the array—indices start at 0 |
boolean isEmpty() | returns true if the array is empty |
void remove(int index) | removes the element at index |
void clear() | clears the array of all its elements |
Object[] toArray() | converts the dynamic array into a standard array |
String toString() | returns a string representing the array |
Here is a test program:
// imported classes
import java.util.*;
public class test1{
// The main program - static - class method
public static void main(String arg[]){
// Creating class instance objects
person p = new person("Jean", "Dupont", 30);
teacher t = new Teacher("Paula", "Hanson", 56, 27);
student student = new Student("Chris", "Garot", 22, "19980405");
System.out.println("p=" + p);
System.out.println("en=" + en);
System.out.println("student = " + student);
// polymorphism
person p2 = (person) en;
System.out.println("p2=" + p2);
Person p3 = (Person) et;
System.out.println("p3=" + p3);
// an array
ArrayList people = new ArrayList();
people.add(p); people.add(en); people.add(et);
System.out.println("Number of people = " + people.size());
for(int i=0;i<people.size();i++){
p2 = (Person) people.get(i);
System.out.println("people[" + i + "] = " + p2);
}
} // end of main
}// end class
The results obtained are the same as before.
4.6. The Arrays Class
The java.util.Arrays class provides access to static methods that allow various operations on arrays, particularly sorting and searching for elements. Here are a few of these methods:
static void sort(array) | sorts the array using the implicit order of the array’s data type, whether numbers or strings. |
static void sort(Object[] array, Comparator C) | Sorts the array using the comparison function C to compare elements |
static int binarySearch(array, element) | Returns the position of element in array, or a value <0 otherwise. The array must be sorted beforehand. |
static int binarySearch(Object[] array, Object element, Comparator C) | Same as above, but uses the comparison function C to compare two elements in the array. |
Here is a first example:
import java.util.*;
public class sort2 implements Comparator{
// an internal private class
private class Person{
private String name;
private int age;
public Person(String name, int age) {
this.name = name; // person's name
this.age = age; // their age
}
// get the age
public int getAge(){
return age;
}
// person's identity
public String toString(){
return ("[" + name + "," + age + "]");
}
}; // Person class
// constructor
public sort2() {
// an array of people
person[] friends = new person[] { new person("Tintin", 100), new person("Snowy", 80),
new Person("Sunflower", 40));
// Sort the array of people
Arrays.sort(friends, this);
// verification
for(int i=0;i<3;i++)
System.out.println(friends[i]);
}//constructor
// the function that compares people
public int compare(Object o1, Object o2){
// must return
// -1 if o1 is "smaller than" o2
// 0 if o1 is "equal to" o2
// +1 if o1 "greater than" o2
person p1 = (person)o1;
person p2 = (person) o2;
int age1 = p1.getAge();
int age2 = p2.getAge();
if(age1<age2) return (-1);
else if (age1 == age2) return (0);
else return +1;
}//compare
// test function
public static void main(String[] arg){
new sort2();
}//main
}//class
Let's examine this program. The main function creates a sort2 object. The constructor for the sort2 class is as follows:
// constructor
public sort2() {
// an array of people
person[] friends = new person[] {new person("Tintin", 100), new person("Snowy", 80),
new Person("Sunflower", 40));
// Sort the array of people
Arrays.sort(friends, this);
// verification
for(int i=0;i<3;i++)
System.out.println(friends[i]);
}//constructor
The array to be sorted is an array of Person objects. The Person class is defined as private within the sort2 class. The static sort method of the Arrays class does not know how to sort an array of Person objects, so we are forced here to use the form void sort(Object[] obj, Comparator C). Comparator is an interface that defines only one method:
and which must return 0 if o1=o2, -1: if o1 < o2, +1: if o1 > o2. In the prototype void sort(Object[] obj, Comparator C), the second argument C must be an object that implements the Comparator interface. In the sort2 constructor, we have chosen the current object this:
This requires us to do two things:
- indicate that the sort2 class implements the Comparator interface
```java
public class sort2 implements Comparator{
```
- write the compare function in the sort2 class.
This is as follows:
// the function that compares objects
public int compare(Object o1, Object o2){
// must return
// -1 if o1 is "smaller than" o2
// 0 if o1 is "equal to" o2
// +1 if o1 is "greater than" o2
person p1 = (person)o1;
person p2 = (person) o2;
int age1 = p1.getAge();
int age2 = p2.getAge();
if (age1 < age2) return (-1);
else if (age1 == age2) return (0);
else return +1;
}//compare
To compare two Person objects, we use age here (we could have used the name).
The results of the execution are as follows:
We could have taken a different approach to implementing the Comparator interface:
import java.util.*;
public class sort2 {
// an internal private class
private class Person {
…….
}; // Person class
// constructor
public person() {
// an array of people
person[] friends = new person[] { new person("Tintin", 100), new person("Snowy", 80),
new Person("Sunflower", 40));
// Sort the array of people
Arrays.sort(friends,
new java.util.Comparator(){
public int compare(Object o1, Object o2){
return compare1(o1, o2);
}//compare
}//class
);
// verification
for(int i=0;i<3;i++)
System.out.println(friends[i]);
}//constructor
// the function that compares people
public int compare1(Object o1, Object o2){
// must return
// -1 if o1 is "smaller than" o2
// 0 if o1 is "equal to" o2
// +1 if o1 is "greater than" o2
person p1 = (person)o1;
person p2 = (person) o2;
int age1 = p1.getAge();
int age2 = p2.getAge();
if(age1<age2) return (-1);
else if (age1 == age2) return (0);
else return +1;
}//compare1
// main
public static void main(String[] arg){
new sort2();
}//main
}//class
The sorting statement has become the following:
// Sort the array of people
Arrays.sort(friends,
new java.util.Comparator(){
public int compare(Object o1, Object o2){
return compare1(o1, o2);
}//compare
}//class
);
The second parameter of the compare method must be an object that implements the Comparator interface. Here, we create such an object using new java.util.Comparator(), and the text that follows {…} defines the class from which the object is created. This is called an anonymous class because it has no name. In this anonymous class, which must implement the Comparator interface, we define the compare method of that interface. This method simply calls the compare1 method of the sort2 class. We are then back to the previous case.
The sort2 class no longer implements the Comparator interface. Therefore, its declaration becomes:
Now we test the binarySearch method of the Arrays class using the following example:
import java.util.*;
public class sort4 {
// an internal private class
private class Person {
// attributes
private String name;
private int age;
// public constructor
public Person(String name, int age) {
this.name = name; // person's name
this.age = age; // their age
}
// retrieve the name
public String getName(){
return name;
}
// get age
public int getAge(){
return age;
}
// person's identity
public String toString(){
return ("[" + name + "," + age + "]");
}
}; // Person class
// constructor
public Person() {
// an array of people
person[] friends = new person[] { new person("Tintin", 100), new person("Snowy", 80),
new Person("Sunflower", 40));
// comparators
java.util.Comparator comparator1 =
new java.util.Comparator(){
public int compare(Object o1, Object o2){
return comparator1(o1, o2);
}//compare
}//class
;
java.util.Comparator comparator2 =
new java.util.Comparator(){
public int compare(Object o1, Object o2){
return compare2(o1, o2);
}//compare
}//class
;
// Sort the array of people
Arrays.sort(friends, comparator1);
// verification
for(int i=0;i<3;i++)
System.out.println(friends[i]);
// search
search("milou", friends, comparator2);
search("xx", friends, comparator2);
}//constructor
// the function that compares people
public int compare1(Object o1, Object o2){
// must return
// -1 if o1 is "smaller than" o2
// 0 if o1 is "equal to" o2
// +1 if o1 is "greater than" o2
person p1 = (person)o1;
person p2 = (person) o2;
int age1 = p1.getAge();
int age2 = p2.getAge();
if (age1 < age2) return (-1);
else if (age1 == age2) return (0);
else return +1;
}//compare1
// the function that compares a person to a name
public int compare2(Object o1, Object o2){
// o1 is a person
// o2 is a String, the name name2 of a person
// must return
// -1 if o1.name is "less than" name2
// 0 if o1.name is "equal to" name2
// +1 if o1.name is "greater than" name2
person p1 = (person) o1;
String name1 = p1.getName();
String name2 = (String)o2;
return name1.compareTo(name2);
}//compare2
public void search(String friend, Person[] friends, Comparator comparator) {
// search for friend in the friends array
int position = Arrays.binarySearch(friends, friend, comparator);
// Found?
if (position >= 0)
System.out.println(friend + " is " + friends[position].getAge() + " years old");
else System.out.println(friend + " does not exist in the array");
}//search
// main
public static void main(String[] arg){
new sort4();
}//main
}//class
Here, we have proceeded a little differently from the previous examples. The two Comparator objects required by the sort and binarySearch methods have been created and assigned to the variables comparator1 and comparator2.
// comparators
java.util.Comparator comparator1 =
new java.util.Comparator(){
public int compare(Object o1, Object o2){
return compare1(o1, o2);
}//compare
}//class
;
java.util.Comparator comparator2 =
new java.util.Comparator(){
public int compare(Object o1, Object o2){
return compare2(o1, o2);
}//compare
}//class
;
A binary search on the friends array is performed twice in the sort4 constructor:
The search method receives all the parameters it needs to call the binarySearch method:
public void search(String friend, Person[] friends, Comparator comparator) {
// search for friend in the friends array
int position = Arrays.binarySearch(friends, friend, comparator);
// Found?
if (position >= 0)
System.out.println(friend + " is " + friends[position].getAge() + " years old");
else System.out.println(friend + " does not exist in the array");
}//search
The binarySearch method works with the comparator2 comparator, which in turn calls the compare2 method of the sort4 class. The method returns the position of the searched name in the array if it exists, or a number <0 otherwise. The compare2 method is used to compare a Person object to a String-type name.
// the function that compares a person to a name
public int compare2(Object o1, Object o2){
// o1 is a person
// o2 is a String, the name name2 of a person
// must return
// -1 if o1.name is "less than" name2
// 0 if o1.name is "equal to" name2
// +1 if o1.name is "greater than" name2
person p1 = (person) o1;
String name1 = p1.getName();
String name2 = (String)o2;
return name1.compareTo(name2);
}//compare2
Unlike the sort method, the binarySearch method does not take two Person objects, but rather a Person object and a String object in that order. The first parameter is an element of the friends array, and the second is the name of the person being searched for.
4.7. The Enumeration class
Enumeration is an interface, not a class. It has the following methods:
public abstract boolean hasMoreElements() | returns true if the enumeration still has elements |
public abstract Object nextElement() | returns a reference to the next element in the enumeration |
How do you use an enumeration? Generally like this:
Enumeration e = … // retrieve an enumeration object
while(e.hasMoreElements()){
// access the element e.nextElement()
}
Here is an example:
// imported classes
import java.util.*;
public class test1{
// the main program - static - class method
public static void main(String arg[]){
// Creating class instance objects
person p = new person("Jean", "Dupont", 30);
teacher en = new Teacher("Paula", "Hanson", 56, 27);
student student = new Student("Chris", "Garot", 22, "19980405");
System.out.println("p=" + p.toString());
System.out.println("en=" + en.toString());
System.out.println("student = " + student.toString());
// polymorphism
person p2 = (person) en;
System.out.println("p2=" + p2.toString());
Person p3 = (Person) et;
System.out.println("p3=" + p3.toString());
// a vector
Vector V = new Vector();
V.addElement(p); V.addElement(en); V.addElement(et);
System.out.println("Size of vector V = " + V.size());
int i;
for (i = 0; i < V.size(); i++) {
p2 = (Person) V.elementAt(i);
System.out.println("V[" + i + "] = " + p2.toString());
}
// an enumeration
Enumeration E = V.elements();
i=0;
while(E.hasMoreElements()){
p2 = (Person) E.nextElement();
System.out.println("V[" + i + "] = " + p2.toString());
i++;
}
}// end of main
}//end class
The following results are obtained:
p = person(Jean, Dupont, 30)
en=teacher(person(Paula,Hanson,56),27)
student(person(Chris,Garot,22),19980405)
p2 = teacher(person(Paula, Hanson, 56), 27)
p3 = student(person(Chris, Garot, 22), 19980405)
Size of vector V = 3
V[0] = person(Jean, Dupont, 30)
V[1] = teacher(person(Paula, Hanson, 56), 27)
V[2] = student(person(Chris, Garot, 22), 19980405)
V[0] = person(Jean, Dupont, 30)
V[1] = teacher(person(Paula, Hanson, 56), 27)
V[2] = student(person(Chris, Garot, 22), 19980405)
4.8. The HashTable class
The HashTable class allows you to implement a dictionary. A dictionary can be viewed as a two-column array:
key | value |
key1 | value1 |
key2 | value2 |
.. | ... |
Keys are unique, i.e., there cannot be two identical keys. The main methods and properties of the Hashtable class are as follows:
public Hashtable() | constructor - creates an empty dictionary |
public int size() | number of elements in the dictionary—where an element is a pair (key, value) |
public Object put(Object key, Object value) | adds the pair (key, value) to the dictionary |
public Object get(Object key) | retrieves the object associated with the key key or null if the key key does not exist |
public boolean containsKey(Object key) | true if the key exists in the dictionary |
public boolean contains(Object value) | true if the value value exists in the dictionary |
public Enumeration keys() | returns the keys of the dictionary as an enumeration |
public Object remove(Object key) | removes the (key, value) pair where key=key |
public String toString() | identifies the dictionary |
Here is an example:
// imported classes
import java.util.*;
public class test1{
// the main program main - static - class method
public static void main(String arg[]){
// Creating class instance objects
person p = new person("Jean", "Dupont", 30);
teacher en = new Teacher("Paula", "Hanson", 56, 27);
student student = new Student("Chris", "Garot", 22, "19980405");
System.out.println("p=" + p.toString());
System.out.println("en=" + en.toString());
System.out.println("student = " + student.toString());
// polymorphism
person p2 = (person) en;
System.out.println("p2=" + p2.toString());
Person p3 = (Person) et;
System.out.println("p3=" + p3.toString());
// a dictionary
Hashtable H = new Hashtable();
H.put("person1", p);
H.put("person2", en);
H.put("person3", et);
Enumeration E = H.keys();
int i = 0;
String key;
while (E.hasMoreElements()) {
key = (String) E.nextElement();
p2 = (Person) H.get(key);
System.out.println("key " + i + " = " + cle + " value=" + p2.toString());
i++;
}
}//end main
}//end class
The results are as follows:
p = person(Jean, Dupont, 30)
en=teacher(person(Paula,Hanson,56),27)
student = student(person(Chris, Garot, 22), 19980405)
p2 = teacher(person(Paula, Hanson, 56), 27)
p3=student(person(Chris,Garot,22),19980405)
key 0=person3 value=student(person(Chris,Garot,22),19980405)
key 1=person2 value=teacher(person(Paula,Hanson,56),27)
key 2=person1 value=person(Jean,Dupont,30)
4.9. Text files
4.9.1. Writing
To write to a file, you need a write stream. You can use the FileWriter class for this. The following constructors are commonly used:
FileWriter(String fileName) | creates a file named fileName—you can then write to it—any existing file with the same name is overwritten |
FileWriter(String fileName, boolean append) | same as above—any existing file with the same name can be used by opening it in append mode (append=true) |
The FileWriter class provides a number of methods for writing to a file, methods inherited from the Writer class. To write to a text file, it is preferable to use the PrintWriter class, whose commonly used constructors are as follows:
PrintWriter(Writer out) | the argument is of type Writer, i.e., a write stream (to a file, over the network, etc.) |
PrintWriter(Writer out, boolean autoflush) | Same as above. The second argument controls line buffering. When set to false (the default), lines written to the file pass through an in-memory buffer. When the buffer is full, it is written to the file. This improves disk access. That said, this behavior is sometimes undesirable, particularly when writing over a network. |
The useful methods of the PrintWriter class are as follows:
void print(Type T) | writes the data T (String, int, ….) |
void println(Type T) | same as above, ending with a newline character |
void flush() | flushes the buffer if not in autoflush mode |
void close() | closes the write stream |
Here is a program that writes a few lines to a text file:
// imports
import java.io.*;
public class write{
public static void main(String[] arg){
// open the file
PrintWriter fic = null;
try{
fic = new PrintWriter(new FileWriter("out"));
} catch (Exception e){
Error(e, 1);
}
// write to file
try{
fic.println("Jean,Dupont,27");
fic.println("Pauline,Garcia,24");
fic.println("Gilles,Dumond,56");
} catch (Exception e){
Error(e, 3);
}
// Close the file
try{
fic.close();
} catch (Exception e){
Error(e, 2);
}
}// end of main
private static void Error(Exception e, int code){
System.err.println("Error: " + e);
System.exit(code);
}//Error
}//class
The output file generated by the program is as follows:
4.9.2. Reading
To read the contents of a file, you need a read stream associated with the file. You can use the FileReader class and the following constructor for this:
FileReader(String filename) | opens a read stream from the specified file. Throws an exception if the operation fails. |
The FileReader class has a number of methods for reading from a file, methods inherited from the Reader class. To read lines of text from a text file, it is preferable to use the BufferedReader class with the following constructor:
BufferedReader(Reader in) | opens a buffered read stream from an input stream in. This Reader-type stream can come from the keyboard, a file, the network, etc. |
The useful methods of the BufferedReader class are as follows:
int read() | reads a character |
String readLine() | reads a line of text |
int read(char[] buffer, int offset, int size) | Reads size characters from the file and places them in the buffer array starting at position offset. |
void close() | closes the read stream |
Here is a program that reads the contents of the file created earlier:
// imported classes
import java.util.*;
import java.io.*;
public class read{
public static void main(String[] arg){
person p = null;
// Open the file
BufferedReader IN = null;
try{
IN = new BufferedReader(new FileReader("out"));
} catch (Exception e){
Error(e, 1);
}
// data
String line = null;
String[] fields = null;
String lastName = null;
String lastName = null;
int age = 0;
// error handling
try{
while ((line = IN.readLine()) != null) {
fields = line.split(",");
firstName = fields[0];
lastName = fields[1];
age = Integer.parseInt(fields[2]);
System.out.println("" + new Person(firstName, lastName, age));
}// end of while
} catch (Exception e){
Error(e, 2);
}
// close file
try{
IN.close();
} catch (Exception e){
Error(e, 3);
}
}// end of main
// Error
public static void Error(Exception e, int code){
System.err.println("Error: " + e);
System.exit(code);
}
}// end of class
Running the program produces the following results:
4.9.3. Saving a person object
We apply what we just saw to provide the Person class with a method that allows us to save a person’s attributes to a file. We add the saveAttributes method to the Person class definition:
// ------------------------------
// save to text file
// ------------------------------
public void saveAttributes(PrintWriter P){
P.println(""+this);
}
Before defining the Person class, don't forget to import the java.io package:
The saveAttributes method takes a single parameter: the PrintWriter stream to which it must write. A test program might look like this:
// imports
import java.io.*;
// import Person;
public class save{
public static void main(String[] arg){
// Open the file
PrintWriter fic = null;
try{
fic = new PrintWriter(new FileWriter("out"));
} catch (Exception e){
Error(e, 1);
}
// write to file
try{
new person("Jean", "Dupont", 27).saveAttributes(file);
new person("Pauline", "Garcia", 24).saveAttributes(file);
new person("Gilles", "Dumond", 56).saveAttributes(file);
} catch (Exception e){
Error(e, 3);
}
// Close the file
try{
fic.close();
} catch (Exception e){
Error(e, 2);
}
}// end of main
// Error
private static void Error(Exception e, int code){
System.err.println("Error: " + e);
System.exit(code);
}//Error
}//class
Let's compile and run this program:
E:\data\serge\JAVA\poly June 2002\Chapter 3\sauveAttributs>javac sauver.java
E:\data\serge\JAVA\poly June 2002\Chapter 3\saveAttributes>dir
06/10/2002 10:52 1,352 person.class
06/10/2002 10:53 842 save.java
06/10/2002 10:53 1,258 save.class
E:\data\serge\JAVA\poly June 2002\Chapter 3\saveAttributes>java save
E:\data\serge\JAVA\poly June 2002\Chapter 3\saveAttributes>dir
06/10/2002 10:52 1,352 person.class
June 10, 2002 10:53 842 save.java
06/10/2002 10:53 1,258 save.class
06/10/2002 10:53 83 out
E:\data\serge\JAVA\poly June 2002\Chapter 3\saveAttributes>more out
person(Jean,Dupont,27)
person(Pauline, Garcia, 24)
person(Gilles,Dumond,56)
4.10. Binary files
4.10.1. The RandomAccessFile class
The RandomAccessFile class allows you to manage binary files, particularly those with a fixed structure as found in C/C++. Here are some useful methods and constructors:
RandomAccessFile(String filename, String mode) | constructor - opens the specified file in the specified mode. The mode can be one of the following: r: open for reading rw: open for reading and writing |
void writeTTT(TTT value) | writes value to the file. TTT represents the value type. The memory representation of value is written as-is to the file. Thus, there are writeBoolean, writeByte, writeInt, writeDouble, writeLong, writeFloat, etc. To write a string, use writeBytes(String string). |
TTT readTTT() | Reads and returns a value of type TTT. Examples include readBoolean, readByte, readInt, readDouble, readLong, readFloat, etc. The read() method reads a byte. |
long length() | file size in bytes |
long getFilePointer() | current position of the file pointer |
void seek(long pos) | sets the file cursor to byte pos |
4.10.2. The Article class
All of the following examples will use the following article class:
// the article structure
private static class article{
// defining the structure
public String code;
public String name;
public double price;
public int currentStock;
public int minimumStock;
}//item class
The Java Item class above is equivalent to the following C structure
struct item{
char code[4];
char name[20];
double price;
int currentStock;
int minimumStock;
}//structure
This way, we’ll limit the code to 4 characters and the name to 20.
4.10.3. Write a record
The following program writes a record to a file named "data":
// imported classes
import java.io.*;
public class test1{
// tests writing a structure (in the C sense) to a binary file
// the article structure
private static class article {
// we define the structure
public String code;
public String name;
public double price;
public int currentStock;
public int minimumStock;
}//item class
public static void main(String arg[]){
// Define the binary file in which the items will be stored
RandomAccessFile fic = null;
// define an article
article art = new article();
item.code = "a100";
item.name = "bike";
art.price = 1000.80;
art.currentStock = 100;
art.minStock=10;
// define the file
try{
file = new RandomAccessFile("data", "rw");
} catch (Exception E){
error("Unable to open the data file", 1);
}//try-catch
// we write
try{
write(fic, art);
} catch (IOException e) {
error("Error writing record", 2);
}//try-catch
// done
try{
fic.close();
} catch (Exception E){
error("Unable to close the data file", 2);
}//try-catch
}//main
// write method
public static void write(RandomAccessFile fic, article art) throws IOException{
// code
fic.writeBytes(art.code);
// name limited to 20 characters
art.name = art.name.trim();
int l = art.name.length();
int numSpaces = 20 - l;
if(nbBlancs > 0) {
String whitespaces = "";
for(int i=0;i<nbBlancs;i++) whitespace+=" ";
art.name += spaces;
} else art.name = art.name.substring(0, 20);
fic.writeBytes(art.name);
// the price
fic.writeDouble(art.price);
// stock
fic.writeInt(item.currentStock);
fic.writeInt(art.stockMinimum);
}// end write
// ------------------------error
public static void error(String msg, int exitCode){
System.err.println(msg);
System.exit(exitCode);
}// end error
}// end class
The following program allows us to verify that the execution was successful.
4.10.4. Read a record
// imported classes
import java.io.*;
public class test2{
// tests writing a structure (in the C sense) to a binary file
// the article structure
private static class article{
// we define the structure
public String code;
public String name;
public double price;
public int currentStock;
public int minimumStock;
}//item class
public static void main(String arg[]){
// define the binary file in which the items will be stored
RandomAccessFile fic = null;
// open the file for reading
try{
fic = new RandomAccessFile("data", "r");
} catch (Exception E){
error("Unable to open the data file", 1);
}//try-catch
// read the single article from the file
article art = new article();
try{
read(file, art);
} catch (IOException E){
error("Error reading record", 2);
}//try-catch
// display the read record
display(art);
// done
try{
fic.close();
} catch (Exception E){
error("Unable to close the data file", 2);
}//try-catch
}// end of main
// read method
public static void read(RandomAccessFile fic, article art) throws IOException{
// read code
art.code="";
for(int i=0;i<4;i++) art.code+=(char)fic.readByte();
// name
art.name="";
for(int i=0;i<20;i++) art.name+=(char)fic.readByte();
art.name = art.name.trim();
// price
item.price = fic.readDouble();
// stock
item.currentStock = fic.readInt();
item.minStock = file.readInt();
}// end write
// ---------------------display
public static void display(item item){
System.out.println("code: " + art.code);
System.out.println("name: " + art.name);
System.out.println("price: " + art.price);
System.out.println("Current stock: " + art.currentStock);
System.out.println("Minimum stock: " + art.minStock);
}// end of display
// ------------------------error
public static void error(String msg, int exitCode){
System.err.println(msg);
System.exit(exitCode);
}// end error
}// end class
The execution results are as follows:
E:\data\serge\JAVA\random>java test2
code: a100
name: bike
price: 1000.8
Current stock: 100
Minimum stock: 10
We successfully retrieve the record that was written by the writing program.
4.10.5. Text to Binary Conversion
The following program is an extension of the record-writing program. We now write multiple records to a binary file named data.bin. The data is taken from the following data.txt file:
E:\data\serge\JAVA\random>more data.txt
a100:bike:1000:100:10
b100:pump:65:6:2
c100:bow:867:10:5
d100:arrows - pack of 6:450:12:8
e100:toy:10:2:3
// imported classes
import java.io.*;
import java.util.*;
public class test3{
// text file --> binary file
// the article structure
private static class article {
// defining the structure
public String code;
public String name;
public double price;
public int currentStock;
public int minimumStock;
}//item class
public static void main(String arg[]){
// we define the binary file in which the items will be stored
RandomAccessFile dataBin = null;
try{
dataBin = new RandomAccessFile("data.bin", "rw");
} catch (Exception E) {
error("Unable to open the file data.bin", 1);
}
// Data is read from a text file
BufferedReader dataTxt = null;
try{
dataTxt = new BufferedReader(new FileReader("data.txt"));
} catch (IOException E) {
error("Unable to open the data.txt file", 2);
}
// .txt file --> .bin file
String line = null;
String[] fields = null;
int lineNumber = 0;
String field = null;
article art = new article(); // Create item
try{
while((line = dataTxt.readLine()) != null) {
// a line of +
lineNumber++;
// split into fields
fields = line.split(":");
// 5 fields are required
if(fields.length!=5)
error("Invalid line " + numLine + " in data.txt", 3);
//code
item.code = fields[0];
if(art.code.length()!=4)
error("Invalid code on line " + lineNumber + " in data.txt", 12);
// last name, first name
art.lastName = fields[1];
// price
try{
item.price = Double.parseDouble(fields[2]);
} catch (Exception E){
error("Invalid price in line " + lineNumber + " of the data.txt file", 4);
}
// current stock
try{
currentStock = Integer.parseInt(fields[3]);
} catch (Exception E) {
error("Incorrect current stock in line " + lineNumber + " of the data.txt file", 5);
}
// current stock
try{
currentStock = Integer.parseInt(fields[3]);
} catch (Exception E){
error("Incorrect current stock in line " + lineNumber + " of the data.txt file", 5);
}
// write the record
try{
write(dataBin, art);
} catch (IOException E){
error("Error writing record " + lineNumber, 7);
}
// move to the next line
}// end of while
} catch (IOException E){
error("Error reading the data.txt file after line " + lineNumber, 8);
}
// done
try{
dataBin.close();
} catch (Exception E){
error("Unable to close the data.bin file", 10);
}
try{
dataTxt.close();
} catch (Exception E){
error("Unable to close the data.txt file", 11);
}
}// end of main
// write method
public static void write(RandomAccessFile fic, article art) throws IOException{
// code
fic.writeBytes(art.code);
// name limited to 20 characters
art.name = art.name.trim();
int l = art.name.length();
int blankCount = 20 - l;
if(nbBlanks > 0) {
String whitespacing = "";
for(int i=0;i<nbBlanks;i++) blanks+=" ";
art.name += spaces;
} else art.name = art.name.substring(0, 20);
fic.writeBytes(art.name);
// the price
fic.writeDouble(art.price);
// stock
fic.writeInt(item.currentStock);
fic.writeInt(art.minStock);
}// end write
// ------------------------error
public static void error(String msg, int exitCode){
System.err.println(msg);
System.exit(exitCode);
}// end error
}// end class
The following program allows you to verify that this one worked correctly.
4.10.6. Binary to text conversion
The following program reads the contents of the binary file data.bin created earlier and writes its contents to the text file data.text. If everything goes well, the file data.text should be identical to the original file data.txt.
// imported classes
import java.io.*;
import java.util.*;
public class test5{
// text file --> binary file
// the article structure
private static class article {
// defining the structure
public String code;
public String name;
public double price;
public int currentStock;
public int minimumStock;
}//item class
// main
public static void main(String arg[]){
// define the binary file in which the items will be stored
RandomAccessFile dataBin = null;
try{
dataBin = new RandomAccessFile("data.bin", "r");
} catch (Exception E){
error("Unable to open the file data.bin for reading", 1);
}
// The data is written to a text file
PrintWriter dataTxt = null;
try{
dataTxt = new PrintWriter(new FileWriter("data.text"));
} catch (IOException e) {
error("Unable to open the file data.text for writing", 2);
}
// .bin file --> .text file
article art=new article(); // article to be created
// process the binary file
int numRecord = 0;
long l = 0; // file size
try{
l = dataBin.length();
} catch (IOException e){
error("Error calculating the length of the data.bin file", 2);
}
long pos = 0; // current position in the file
try{
pos = dataBin.getFilePointer();
} catch (IOException e){
error("Error reading current position in data.bin", 2);
}
// as long as we haven't reached the end of the file
while(pos < l){
// read current record and process it
numRecord++;
try{
read(dataBin, art);
} catch (Exception e){
error("Error reading record " + numRecord, 2);
}
display(art);
// Write the corresponding text line to dataTxt
dataTxt.println(art.code.trim() + ":" + art.name.trim() + ":" + art.price + ":" + art.currentStock + ":" + art.minStock);
// continue?
try{
pos = dataBin.getFilePointer();
} catch (IOException e){
error("Error reading the current position in data.bin", 2);
}
}// end of while
// It's over
try{
dataBin.close();
} catch (Exception E){
error("Unable to close the data.bin file", 2);
}
try{
dataTxt.close();
} catch (Exception E){
error("Unable to close the data.text file", 2);
}
}// end of main
// read method
public static void read(RandomAccessFile fic, article art) throws IOException{
// read code
art.code = "";
for(int i=0;i<4;i++) art.code+=(char)fic.readByte();
// name
art.name = "";
for(int i=0;i<20;i++) art.name+=(char)fic.readByte();
art.name = art.name.trim();
// price
item.price = fic.readDouble();
// stock
item.currentStock = fic.readInt();
item.minStock = file.readInt();
}// end write
// ---------------------display
public static void display(item item){
System.out.println("code: " + art.code);
System.out.println("name: " + art.name);
System.out.println("price: " + art.price);
System.out.println("Current stock: " + art.currentStock);
System.out.println("Minimum stock: " + art.minStock);
}// end of display
// ------------------------error
public static void error(String msg, int exitCode){
System.err.println(msg);
System.exit(exitCode);
}// end error
}// end class
Here is an example of execution:
E:\data\serge\JAVA\random>java test5
code: a100
name: bike
price: 1000.0
Current stock: 100
Minimum stock: 0
code: b100
Name: Pump
Price: 65.0
Current stock: 6
Minimum stock: 0
code: c100
Name: Bow
Price: 867.0
Current stock: 10
Minimum stock: 0
Code: d100
Name: Arrows - Set of 6
Price: 450.0
Current stock: 12
Minimum stock: 0
code: e100
Name: Toy
Price: 10.0
Current stock: 2
Minimum stock: 0
E:\data\serge\JAVA\random>more data.text
a100:bike:1000.0:100:0
b100:pump:65.0:6:0
c100:bow:867.0:10:0
d100:arrows - set of 6:450.0:12:0
e100:toy:10.0:2:0
4.10.7. Direct access to records
This last program demonstrates the ability to directly access records in a binary file. It displays the record from the data.bin file whose number is passed as a parameter, with the first record having the number 1.
// imported classes
import java.io.*;
import java.util.*;
public class test6{
// text file --> binary file
// the article structure
private static class article {
// defining the structure
public String code;
public String name;
public double price;
public int currentStock;
public int minimumStock;
}//item class
// main
public static void main(String[] args){
// check the arguments
int numArguments = args.length;
String syntax = "syntax: pg record_number";
if(nbArguments!=1)
error(syntax, 20);
// check record number
int recordNumber = 0;
try{
numRecord = Integer.parseInt(args[0]);
} catch (Exception e) {
error(syntax + "\nInvalid record number", 21);
}
// Open the binary file for reading
RandomAccessFile dataBin = null;
try{
dataBin = new RandomAccessFile("data.bin", "r");
} catch (Exception E){
error("Unable to open the file data.bin for reading", 1);
}
// move to the desired record
try{
dataBin.seek((numRecord-1)*40);
} catch (Exception e){
error("Record " + numRecord + " does not exist", 23);
}
// read it
article art = new article();
try{
read(dataBin, art);
} catch (Exception e){
error("Error reading record " + numRecord, 2);
}
// display it
display(art);
// done
try{
dataBin.close();
} catch (Exception E){
error("Unable to close the data.bin file", 2);
}//try-catch
}// end of main
// read method
public static void read(RandomAccessFile fic, Article art) throws IOException{
// read code
art.code = "";
for(int i=0;i<4;i++) art.code+=(char)fic.readByte();
// name
art.name = "";
for(int i=0;i<20;i++) art.name+=(char)fic.readByte();
art.name = art.name.trim();
// price
item.price = fic.readDouble();
// stock
item.currentStock = fic.readInt();
item.minStock = file.readInt();
}// end write
// ---------------------display
public static void display(item item){
System.out.println("code: " + art.code);
System.out.println("name: " + art.name);
System.out.println("price: " + art.price);
System.out.println("Current stock: " + art.currentStock);
System.out.println("Minimum stock: " + art.minStock);
}// end of display
// ------------------------error
public static void error(String msg, int exitCode){
System.err.println(msg);
System.exit(exitCode);
}// end error
}// end class
Here are some examples of execution:
E:\data\serge\JAVA\random>java test6 2
code: b100
name: pump
Price: 65.0
Current stock: 6
Minimum stock: 0
E:\data\serge\JAVA\random>java.bat test6 20
Error reading record 20
4.11. Using regular expressions
4.11.1. The java.util.regex package in the Java
The java.util.regex package allows the use of regular expressions. These enable you to validate the format of a string. For example, you can verify that a string representing a date is in the dd/mm/yy format. To do this, you use a pattern and compare the string to that pattern. In this example, d, m, and y must be digits. The pattern for a valid date format is therefore "\d\d/\d\d/\d\d", where the symbol \d represents a digit. The symbols that can be used in a pattern are as follows (Microsoft documentation):
Character | Description |
\ | Designates the following character as a special character or literal. For example, "n" corresponds to the character "n". "\n" corresponds to a newline character. The sequence "\\" corresponds to "\", while "\(" corresponds to "(". |
^ | Matches the start of the input. |
$ | Matches the end of the input. |
* | Matches the preceding character zero or more times. Thus, "zo*" matches "z" or "zoo". |
+ | Matches the preceding character one or more times. Thus, "zo+" matches "zoo", but not "z". |
? | Matches the preceding character zero or one time. For example, "a?ve?" matches "ve" in "lever". |
. | Matches any single character, except the newline character. |
(pattern) | Searches for the pattern and stores the match. The matching substring can be retrieved from the resulting Matches collection using Item [0]...[n]. To find matches with characters inside parentheses ( ), use "\(" or "\)". |
x|y | Matches either x or y. For example, "z|foot" matches "z" or "foot". "(z|f)oo" matches "zoo" or "foo". |
{n} | n is a non-negative integer. Matches exactly n occurrences of the character. For example, "o{2}" does not match "o" in "Bob," but matches the first two "o"s in "fooooot". |
{n,} | n is a non-negative integer. Matches at least n occurrences of the character. For example, "o{2,}" does not match "o" in "Bob," but matches all "o"s in "fooooot." "o{1,}" is equivalent to "o+" and "o{0,}" is equivalent to "o*." |
{n,m} | m and n are non-negative integers. Matches at least n and at most m occurrences of the character. For example, "o{1,3}" matches the first three "o"s in "foooooot" and "o{0,1}" is equivalent to "o?". |
[xyz] | Character set. Matches any of the specified characters. For example, "[abc]" matches "a" in "plat". |
[^xyz] | Negative character set. Matches any character not listed. For example, "[^abc]" matches "p" in "plat". |
[a-z] | Character range. Matches any character in the specified range. For example, "[a-z]" matches any lowercase alphabetical character between "a" and "z". |
[^m-z] | Negative character range. Matches any character not in the specified range. For example, "[^m-z]" matches any character not between "m" and "z". |
\b | Matches a word boundary, that is, the position between a word and a space. For example, "er\b" matches "er" in "lever," but not "er" in "verb." |
\B | Matches a boundary that does not represent a word. "en*t\B" matches "ent" in "bien entendu". |
\d | Matches a character representing a digit. Equivalent to [0-9]. |
\D | Matches a character that is not a digit. Equivalent to [^0-9]. |
\f | Matches a line break character. |
\n | Matches a newline character. |
\r | Equivalent to a carriage return character. |
\s | Matches any whitespace, including space, tab, page break, etc. Equivalent to "[ \f\n\r\t\v]". |
\S | Matches any non-whitespace character. Equivalent to "[^ \f\n\r\t\v]". |
\t | Matches a tab character. |
\v | Matches a vertical tab character. |
\w | Matches any character representing a word and including an underscore. Equivalent to "[A-Za-z0-9_]". |
\W | Matches any character that does not represent a word. Equivalent to "[^A-Za-z0-9_]". |
\num | Matches num, where num is a positive integer. Refers to stored matches. For example, "(.)\1" matches two consecutive identical characters. |
|
An element in a pattern may appear once or multiple times. Let’s look at some examples involving the \d symbol, which represents a single digit:
pattern | meaning |
\d | a digit |
\d? | 0 or 1 digit |
\d* | 0 or more digits |
\d+ | 1 or more digits |
\d{2} | 2 digits |
\d{3,} | at least 3 digits |
\d{5,7} | between 5 and 7 digits |
Now let’s imagine a model capable of describing the expected format for a string:
target string | pattern |
a date in dd/mm/yy format | \d{2}/\d{2}/\d{2} |
a time in hh:mm:ss format | \d{2}:\d{2}:\d{2} |
an unsigned integer | \d+ |
a sequence of spaces, which may be empty | \s* |
an unsigned integer that may be preceded or followed by spaces | \s*\d+\s* |
an integer that may be signed and preceded or followed by spaces | \s*[+|-]?\s*\d+\s* |
an unsigned real number that may be preceded or followed by spaces | \s*\d+(.\d*)?\s* |
a real number that may be signed and preceded or followed by spaces | \s*[+|]?\s*\d+(.\d*)?\s* |
a string containing the word "just" | \bjuste\b |
You can specify where to search for the pattern in the string:
pattern | meaning |
^pattern | the pattern starts the string |
pattern$ | the pattern ends the string |
^pattern$ | the pattern starts and ends the string |
pattern | the pattern is searched for anywhere in the string, starting from the beginning. |
search string | pattern |
a string ending with an exclamation point | !$ |
a string ending with a period | \.$ |
a string beginning with the sequence // | ^// |
a string consisting of a single word, optionally followed or preceded by spaces | ^\s*\w+\s*$ |
a string consisting of two words, optionally followed or preceded by spaces | ^\s*\w+\s*\w+\s*$ |
a string containing the word secret | \bsecret\b |
Sub-patterns of a pattern can be "extracted." Thus, not only can we verify that a string matches a particular pattern, but we can also extract from that string the elements corresponding to the sub-patterns of the pattern that have been enclosed in parentheses. For example, if we are parsing a string containing a date in the format dd/mm/yy and we also want to extract the elements dd, mm, and yy from that date, we would use the pattern (\d\d)/(\d\d)/(\d\d).
4.11.2. Checking if a string matches a given pattern
The Pattern class allows you to check whether a string matches a given pattern. To do this, use the static method
with: pattern: the pattern to check, string: the string to compare against the pattern. The result is the Boolean value true if string matches pattern, false otherwise.
Here is an example:
import java.io.*;
import java.util.regex.*;
// Regular expression handling
public class regex1 {
public static void main(String[] args){
// a sample regular expression
String pattern1 = "^\\s*\\d+\\s*$";
// compare an instance to the pattern
String example1 = " 123 ";
if (Pattern.matches(pattern1, example1)){
display("[" + example1 + "] matches the pattern [" + pattern1 + "]");
} else {
display("[" + instance1 + "] does not match the pattern [" + pattern1 + "]");
}//if
String example2 = "123a";
if (Pattern.matches(pattern1, instance2)){
display("[" + instance2 + "] matches the pattern [" + pattern1 + "]");
}else{
display("[" + example2 + "] does not match the pattern [" + pattern1 + "]");
}//if
}//main
public static void display(String msg){
System.out.println(msg);
}//display
}//class
and the execution results:
Note that in the pattern "^\s*\d+\s*$", the \ character must be doubled due to Java's specific interpretation of this character. We therefore write: String pattern1="^\\s*\\d+\\s*$";
4.11.3. Finding all elements of a string that match a pattern
Consider the pattern "\d+" and the string " 123 456 789 ". The pattern is found in three different places in the string. The Pattern and Matcher classes allow you to retrieve the different occurrences of a pattern in a string. The Pattern class is the class that handles regular expressions. A regular expression used more than once needs to be "compiled." This speeds up pattern searches in strings. The static compile method does this work:
It takes the pattern string as a parameter and returns a Pattern object. To compare the pattern of a Pattern object to a string, we use the Matcher class. This class allows for the comparison of a pattern to a string. From a Pattern object, it is possible to obtain a Matcher object using the matcher method:
input is the string that is to be compared to the pattern.
So, to compare the pattern "\d+" to the string " 123 456 789 ", you can create a Matcher object as follows:
Using the results object from above, we can retrieve the various occurrences of the pattern in the string. To do this, we use the following methods of the Matcher class:
The find method searches the explored string for the first occurrence of the pattern. A second call to find will search for the next occurrence, and so on. The method returns true if it finds the pattern, false otherwise. The portion of the string corresponding to the last occurrence found by find is obtained using the group method, and its position using the start method. Thus, continuing the previous example, if we want to display all occurrences of the pattern "\d+" in the string " 123 456 789 ", we would write:
while(results.find()){
System.out.println("sequence " + results.group() + " found at position " + results.start());
}//while
The reset method allows you to reset the Matcher object to the beginning of the string being compared against the pattern. This way, the find method will then find the first occurrence of the pattern again.
Here is a complete example:
import java.io.*;
import java.util.regex.*;
// Regular expression handling
public class regex2 {
public static void main(String[] args){
// multiple occurrences of the pattern in the instance
String pattern2="\\d+";
Pattern regex2 = Pattern.compile(pattern2);
String sample3 = " 123 456 789";
// search for occurrences of the pattern in the string
Matcher matcher2 = regex2.matcher(string3);
while(matcher2.find()){
display("sequence " + matcher2.group() + " found at position " + matcher2.start());
}//while
}//Main
public static void display(String msg){
System.out.println(msg);
}//display
}//class
Execution results:
Model=[\d+],instance=[ 123 456 789 ]
There are 3 occurrences of the pattern in the instance
123 at position 2
456 at position 7
789 at position 12
4.11.4. Extracting parts of a pattern
Sub-sets of a pattern can be "extracted." Thus, not only can we verify that a string matches a particular pattern, but we can also extract from that string the elements corresponding to the pattern’s sub-sets that have been enclosed in parentheses. For example, if we are parsing a string containing a date in the format dd/mm/yy and we also want to extract the elements dd, mm, and yy from that date, we would use the pattern (\d\d)/(\d\d)/(\d\d).
Let’s examine the following example:
import java.io.*;
import java.util.regex.*;
// Regular expression handling
public class regex3 {
public static void main(String[] args){
// capturing elements in the pattern
String pattern3 = "(\\d\\d):(\\d\\d):(\\d\\d)";
Pattern regex3 = Pattern.compile(pattern3);
String example4 = "It is 18:05:49";
// check the pattern
Matcher result = regex3.matcher(example4);
if (result.find()){
// the example matches the pattern
display("The instance [" + instance4 + "] matches the pattern [" + pattern3 + "]");
// display the groups
for (int i = 0; i <= result.groupCount(); i++) {
display("groups["+i+"]=["+result.group(i)+"] at position "+result.start(i));
}//for
}else{
// the instance does not match the template
display("The instance["+instance4+" does not match the template ["+template3+"]");
}
}//Main
public static void display(String msg){
System.out.println(msg);
}//display
}//class
Running this program produces the following results:
The instance [It is 18:05:49] corresponds to the pattern [(\d\d):(\d\d):(\d\d)]
groups[0]=[18:05:49] at position 7
groups[1]=[18] at position 7
groups[2]=[05] at position 10
groups[3]=[49] at position 13
The new feature is found in the following code snippet:
// pattern verification
Matcher result = regex3.matcher(example4);
if (result.find()){
// the instance matches the pattern
display("The instance ["+instance4+"] matches the pattern ["+pattern3+"]");
// display the groups
for (int i=0;i<=result.groupCount();i++){
display("group[" + i + "] = [" + result.group(i) + "] at position " + result.start(i));
}//for
}else{
// the instance does not match the template
display("The instance["+instance4+" does not match the template ["+template3+"]");
}
The string example4 is compared to the pattern regex3 using the find method. A match for the pattern regex3 is then found in the string example4. If the pattern includes subsets enclosed in parentheses, these are accessible via various methods of the Matcher class:
public int groupCount()
public String group(int group)
public int start(int group)
The groupCount method returns the number of sub-groups found in the pattern, and group(i) returns sub-group number i. This is found in the string at a position given by start(i). Thus, in the example:
The instance [It is 18:05:49] matches the pattern [(\d\d):(\d\d):(\d\d)]
groups[0] = [18:05:49] at position 7
groups[1] = [18] at position 7
groups[2] = [05] at position 10
groups[3] = [49] at position 13
The first call to the find method will find the string 18:05:49 and automatically create the three subsets defined by the parentheses in the pattern, namely 18, 05, and 49.
4.11.5. A Learning Program
Finding the regular expression that allows us to verify whether a string matches a certain pattern can sometimes be a real challenge. The following program allows you to practice. It asks for a pattern and a string and then indicates whether or not the string matches the pattern.
import java.io.*;
import java.util.regex.*;
// regular expression handling
public class regex4 {
public static void main(String[] args){
// data
String pattern = null, string = null;
Pattern regex = null;
BufferedReader IN = null;
Matcher results = null;
int numberOfOccurrences = 0;
// error handling
try{
// Ask the user for the templates and the instances to compare against them
while(true){
// Input stream
IN = new BufferedReader(new InputStreamReader(System.in));
// Prompt for the model
System.out.print("Enter the pattern to test or 'end' to stop:");
pattern = IN.readLine();
// Done?
if(pattern.trim().toLowerCase().equals("end")) break;
// create the regular expression
regex = Pattern.compile(pattern);
// ask the user for the instances to compare against the pattern
while(true){
System.out.print("Enter the string to compare to the pattern [" + pattern + "] or 'end' to stop:");
string = IN.readLine();
// Done?
if(string.trim().toLowerCase().equals("end")) break;
// create the matcher object
results = regex.matcher(string);
// search for occurrences of the pattern
countOfOccurrences = 0;
while (results.find()) {
// we have a match
countOfOccurrences++;
// display it
System.out.println("I found the match ["+results.group()
+"] at position "+results.start());
// display sub-elements
if(results.groupCount()!=1){
for(int j=1;j<=results.groupCount();j++){
System.out.println("\tsub-element [" + results.group(j) + "] at position " +
results.start(j));
}//for j
}//if
// next string
}//while(results.find())
// Have we found at least one occurrence?
if(nbOccurrences==0){
System.out.println("I did not find any matches for the pattern ["+pattern+"]");
}//if
// next pattern
}//while(true)
}//while(true)
} catch (Exception ex) {
// error
System.err.println("Error: " + ex.getMessage());
// end with error
System.exit(1);
}//try-catch
// end
System.exit(0);
}//Main
}//class
Here is an example of execution:
Type the pattern to test or "end" to stop:\d+
Type the string to compare with the pattern [\d+] or "end" to stop: 123 456 789
I found the match [123] at position 0
I found the match [456] at position 4
I found the match [789] at position 8
Type the string to compare against the pattern [\d+] or "end" to stop: end
Type the pattern to test or "end" to stop: (\d\d):(\d\d)
Type the string to compare against the pattern [(\d\d):(\d\d)] or "end" to stop :14:15
abcd 17:18 xyzt
I found the match [14:15] at position 0
subelement [14] at position 0
subelement [15] at position 3
I found the match [17:18] at position 11
subelement [17] at position 11
subelement [18] at position 14
Type the string to compare against the pattern [(\d\d):(\d\d)] or "end" to stop :end
Type the pattern to test or "end" to stop :^\s*\d+\s*$
Type the string to compare against the pattern [^\s*\d+\s*$] or "end" to stop: 1456
I found a match [ 1456] at position 0
Type the string to compare against the pattern [^\s*\d+\s*$] or "end" to stop :end
Type the pattern to test or "end" to stop: \/s*(\d+)\s*$
Type the string to match against the pattern [^\s*(\d+)\s*$] or "end" to stop: 1456
I found the match [1456] at position 0
subelement [1456] at position 0
Type the string to compare against the pattern [^\s*(\d+)\s*$] or "end" to stop: abcd 1
456
No matches found
Type the string to compare against the pattern [^\s*(\d+)\s*$] or "end" to stop: end
Type the pattern to test or "end" to stop: end
4.11.6. The split method of the Pattern class
Consider a string composed of fields separated by a delimiter string expressed using a regular expression. For example, if the fields are separated by the character , preceded or followed by any number of spaces, the regular expression modeling the field separator string would be "\s*,\s*". The split method of the Pattern class allows us to retrieve the fields in an array:
public String[] split(CharSequence input)
The input string is split into fields, which are separated by a separator matching the pattern of the current Pattern object. To retrieve the fields from a line where the field separator is a comma preceded or followed by any number of spaces, we would write:
// a line
String line = "abc ,, def , ghi";
// a pattern
Pattern pattern = Pattern.compile("\\s*,\\s*");
// splitting the line into fields
String[] fields = pattern.split(line);
You can achieve the same result using the split method of the String class:
public String[] split(String regex)
Here is a test program:
import java.io.*;
import java.util.regex.*;
// Regular expression handling
public class split1 {
public static void main(String[] args){
// a line
String line = "abc ,, def , ghi";
// a pattern
Pattern pattern = Pattern.compile("\\s*,\\s*");
// split line into fields
String[] fields = pattern.split(line);
// display
for (int i = 0; i < fields.length; i++) {
System.out.println("fields[" + i + "] = [" + fields[i] + "]");
}//for
// another way to do it
fields = line.split("\\s*,\\s*");
// display
for(int i=0;i<fields.length;i++){
System.out.println("fields["+i+"]=["+fields[i]+"]");
}//for
}//Main
}//class
Execution results:
fields[0]=[abc]
fields[1] = []
fields[2] = [def]
fields[3] = [ghi]
fields[0] = [abc]
fields[1] = []
fields[2] = [def]
fields[3] = [ghi]
4.12. Exercises
4.12.1. Exercise 1
Under Unix, programs are often called as follows:
$ pg -o1 v1 v2 ... -o2 v3 v4 …
where -oi represents an option and vi a value associated with that option. We want to create an options class that would parse the argument string -o1 v1 v2 ... -o2 v3 v4 … in order to construct the following entities:
ValidOptions | a dictionary (Hashtable) whose keys are the valid oi options. The value associated with the oi key is a vector (Vector) whose elements are the values v1 v2 … associated with the -oi option |
invalidOptions | dictionary (Hashtable) whose keys are the invalid options oi. The value associated with the key oi is a vector (Vector) whose elements are the values v1 v2 … associated with the option -oi |
optionsWithout | string (String) listing the vi values not associated with an option |
error | an integer equal to 0 if there are no errors in the argument list, otherwise: 1: there are invalid call parameters 2: there are invalid options 4: there are values not associated with options If there are multiple types of errors, these values are cumulative. |
An options object can be constructed in 4 different ways:
public options (String arguments, String optionsAcceptable)
arguments | the command-line arguments -o1 v1 v2 ... -o2 v3 v4 … to be parsed |
optionsAcceptable | the list of acceptable options |
Example call: options opt=new options("-u u1 u2 u3 -g g1 g2 -x","-u -g");
Here, both arguments are strings. We will accept cases where these strings have been split into words and placed in an array of strings. This requires three additional constructors:
public options (String[] arguments, String optionsAcceptables)
public options (String arguments, String[] acceptableOptions)
public options (String[] arguments, String[] acceptableOptions)
The options class will have the following interface (getters):
returns a reference to the optionsValides array constructed when the options object was created
returns a reference to the invalidOptions array constructed when the options object was created
Returns a reference to the optionsWithout string constructed when the options object was created
Returns the value of the error attribute created when the options object was created
If there are no errors, displays the values of the optionsValides, optionsInvalides, and optionsSans attributes; otherwise, displays the error number.
Here is a sample program:
import java.io.*;
//import options;
public class test1{
public static void main (String[] arg){
// open the input stream
String line;
BufferedReader IN = null;
try{
IN = new BufferedReader(new InputStreamReader(System.in));
} catch (Exception e){
display(e);
System.exit(1);
}
// Read the arguments of the options constructor (String, string)
String options = null;
String acceptableOptions = null;
while(true){
System.out.print("Options: ");
try{
options = IN.readLine();
} catch (Exception e) {
display(e);
System.exit(2);
}
if(options.length()==0) break;
System.out.print("Valid options: ");
try{
acceptableOptions = IN.readLine();
} catch (Exception e){
display(e);
System.exit(2);
}
System.out.println(new options(options, acceptableOptions));
}// end of while
}//end main
public static void display(Exception e) {
System.err.println("Error: " + e);
}
}//end class
Some results:
C:\Serge\java\options>java test1
Options: 1 2 3 -a a1 a2 -b b1 -c c1 c2 c3 -b b2 b3
Valid options: -a -b
Error 6
Valid options: (-b,b1,b2,b3) (-a,a1,a2)
Invalid options: (-c,c1,c2,c3)
No options: 1 2 3
4.12.2. Exercise 2
We want to create a stringtovector class that allows us to transfer the contents of a String object into a Vector object. This class would be derived from the Vector class:
and would have the following constructor:
private void stringToVector(String S, String separator, int[] desiredFields,
boolean strict){
// creates a vector with the fields from the string S
// the string consists of fields separated by separator
// if separator=null, the string consists of a single field
// only the fields whose indices are in the tDesiredFields array
// are desired. Indices start at 1
// if tDesiredFields=null or has zero elements, all fields are taken
// if strict=true, all desired fields must be present
The class would have the following private attribute:
This attribute is set by the previous constructor with the following values:
0: construction was successful
4: some required fields are missing even though strict=true
The class will also have two methods:
which returns the value of the private error attribute.
which displays the value of the object in the form (error, element 1, element 2, …) where elements i are the elements of the vector constructed from the string.
A test program could look like this:
import java.io.*;
//import stringtovector;
public class test2{
public static void main(String arg[]){
int[] T1 = {1, 3};
System.out.println(new stringtovector("a : b : c :d:e",":",T1,true).identity());
int[] T2 = {1, 3, 7};
System.out.println(new StringToVector("a : b : c : d : e", ":", T2, true).identity());
int[] T3 = {1, 4, 7};
System.out.println(new StringToVector("a : b : c :d:e", ":", T3, false).identity());
System.out.println(new StringToVector("a : b : c : d : e", "", T1, false).identity());
System.out.println(new StringToVector("a : b : c : d : e", null, T1, false).identity());
int[] T4 = {1};
System.out.println(new StringToVector("a : b : c :d:e", "!", T4, true).identity());
int[] T5 = null;
System.out.println(new StringToVector("a : b : c :d:e", ":", T5, true).identity());
System.out.println(new StringToVector("a : b : c :d:e", null, T5, true).identity());
int[] T6 = new int[0];
System.out.println(new StringToVector("a : b : c :d:e", "", T6, true).identity());
int[] T7 = {1, 3, 4};
System.out.println(new stringtovector("a b c d e", " ", T6, true).identity());
}
}
The results:
(0,a,c)
(4, a, c)
(0,a,d)
(0, a : b : c : d : e)
(0, a : b : c : d : e)
(0, a : b : c : d : e)
(0, a, b, c, d, e)
(0,a : b : c :d:e)
(0,a : b : c :d:e)
(0,a,b,c,d,e)
Some tips:
- To split the string S into fields, use the split method of the String class.
- Place the fields of S into a dictionary D indexed by the field number
- Retrieve from the dictionary D only those fields whose keys (indexes) are in the array tChampsVoulus.
4.12.3. Exercise 3
We want to add the following constructor to the stringtovector class:
public stringtovector(String S, String separator, String sDesiredFields, boolean strict){
// creates an array containing the fields of the string S
// which consists of fields separated by separator
// if separator=null, the string forms a single field
// only fields whose indices are in sDesiredFields are needed
// indices start at 1
// if sDesiredFields=null or "", all fields are taken
// if strict=true, all desired fields must be present
The list of desired fields is therefore in a string (String) rather than an array of integers (int[]). The class's private error attribute can be assigned a new value:
2: the string of desired field indices is incorrect
Here is a sample program:
import java.io.*;
//import stringtovector;
public class test1{
public static void main(String arg[]){
String fields = null;
System.out.println(new stringtovector("a: b :c :d:e ",":","1 3",true).identity());
System.out.println(new stringtovector("a: b :c :d:e ",":","1 3 7",true).identity());
System.out.println(new StringToVector("a: b :c :d:e ",":","1 4 7",false).identity());
System.out.println(new stringtovector("a: b :c :d:e ","","1 3",false).identity());
System.out.println(new stringtovector("a: b :c :d:e ",null,"1 3",false).identity());
System.out.println(new StringToVector("a: b :c :d:e ","!","1",true).identity());
System.out.println(new StringToVector("a: b :c :d:e ",":","",true).identity());
System.out.println(new StringToVector("a: b :c :d:e ",":",fields,true).identity());
System.out.println(new StringToVector("a: b :c :d:e ", null, fields, true).identity());
System.out.println(new StringToVector("a: b :c :d:e ","","",true).identity());
System.out.println(new StringToVector("a: b :c :d:e ",":","1 !",true).identity());
System.out.println(new stringToVector("a b c d e", " ", "1 3", false).identity());
}
}
Some results:
(0,a,c)
(4, a, c)
(0,a,d)
(0,a: b :c :d:e)
(0,a: b :c :d:e)
(0, a: b : c : d : e)
(0, a, b, c, d, e)
(0,a,b,c,d,e)
(0,a: b :c :d:e)
(0,a: b :c :d:e)
(2)
(0,a,c)
Some tips:
- You need to revert to the case of the previous constructor by transferring the fields from the sChampsVoulus string into an array of integers. To do this, split sChampsVoulus into fields using a StringTokenizer object, whose countTokens attribute will give the number of fields obtained. You can then create an array of integers of the correct size and fill it with the obtained fields.
- To determine if a field is an integer, use the Integer.parseInt method to convert the field to an integer and handle the exception that will be thrown if this conversion is not possible.
4.12.4. Exercise 4
We want to create a filetovector class that allows us to transfer the contents of a text file into a Vector object. This class would be derived from the Vector class:
and would have the following constructor:
// --------------------- constructor
public filetovector(String filename, String separator, int[] desiredFields, boolean strict, String commentTag){
// creates a vector with the lines from the text file filename
// the lines consist of fields separated by separator
// if separator=null, the line consists of a single field
// only fields whose indices are in tDesiredFields are required
// indices start at 1
// if tDesiredFields=null or empty, all fields are taken
// if strict=true, all desired fields must be present
// if this is not the case, the row is not stored and its index
// is placed in the linesErronees vector
// blank lines are ignored
// as well as lines starting with tagComment if tagComment != null
The class would have the following private attributes:
The error attribute is set by the previous constructor with the following values:
0: construction was successful
1: the file to be processed could not be opened
4: some required fields are missing even though strict=true
8: an I/O error occurred while processing the file
The lignesErronees attribute is a vector whose elements are the numbers of the erroneous lines in the form of character strings. A line is considered erroneous if it cannot provide the requested fields while strict=true.
The class will also have two methods:
which returns the value of the private error attribute.
which displays the value of the object in the form (error, element 1, element 2 …,(l1,l2,…)) where elements i are the elements of the vector constructed from the file and li are the numbers of the erroneous lines.
Here is a sample test :
import java.io.*;
//import filetovector;
public class test2{
public static void main(String arg[]){
int[] T1={1,3};
System.out.println(new filetovector("data.txt", ":", T1, false, "#").identity());
System.out.println(new filetovector("data.txt", ":", T1, true, "#").identity());
System.out.println(new FileVector("data.txt", "", T1, false, "#").identity());
System.out.println(new FileToVector("data.txt", null, T1, false, "#").identity());
int[] T2 = null;
System.out.println(new FileVector("data.txt", ":", T2, false, "#").identity());
System.out.println(new FileVector("data.txt", ":", T2, false, "").identity());
int[] T3 = new int[0];
System.out.println(new FileVector("data.txt", ":", T3, false, null).identity());
}
}
Execution results:
[0,(0,a,c) (0,1,3) (0,azerty,cvf) (0,s)]
[4,(0,a,c) (0,1,3) (0,azerty,cvf),[5]]
[0,(0,a:b:c:d:e) (0,1 :2 : 3: 4: 5) (0,azerty : 1 : cvf : fff: qqqq) (0,s)]
[0,(0,a:b:c:d:e) (0,1 :2 : 3: 4: 5) (0,azerty : 1 : cvf : fff: qqqq) (0,s)]
[0,(0,a,b,c,d,e) (0,1,2,3,4,5) (0,azerty,1,cvf,fff,qqqq) (0,s)]
[0,(0,a,b,c,d,e) (0,1,2,3,4,5) (0,# comment) (0,azerty,1,cvf,fff,qqqq) (0,s)]
[0,(0,a,b,c,d,e) (0,1,2,3,4,5) (0,# comment) (0,azerty,1,cvf,fff,qqqq) (0,s)]
Some tips
-
The text file is processed line by line. The line is split into fields using the stringtovector class discussed earlier.
-
The elements of the vector created from the text file are therefore objects of type stringtovector.
-
The identite method of filetovector can rely on the stringtovector.identite() method to display its elements, as well as on the Vector.toString() method to display the numbers of any erroneous lines.
4.12.5. Exercise 5
We want to add the following constructor to the filetovector class:
public filetovector(String filename, String separator, String desiredFields,
boolean strict, String commentTag){
// creates an array containing the lines from the text file filename
// the lines consist of fields separated by separator
// if separator=null, the line consists of a single field
// only fields whose indices are in desiredFields are needed
// indices start at 1
// if desiredFields = null or empty, all fields are taken
// if strict=true, all desired fields must be present
// if this is not the case, the row is not stored and its index
// is placed in the linesErronees vector
// blank lines are ignored
// as well as lines starting with commentTag if commentTag != null
The list of indexes for the required fields is now in a string (String) instead of an array of integers.
The private error attribute may have an additional value:
2: the string of desired field indices is incorrect
Here is a sample test :
import java.io.*;
//import filetovector;
public class test1{
public static void main(String arg[]){
System.out.println(new filetovector("data.txt",":","1 3",false,"#").identity());
System.out.println(new filetovector("data.txt", ":", "1 3", true, "#").identity());
System.out.println(new filetovector("data.txt", "", "1 3", false, "#").identity());
System.out.println(new FileVector("data.txt", null, " 1 3", false, "#").identity());
String S2 = null;
System.out.println(new FileVector("data.txt", ":", S2, false, "#").identity());
System.out.println(new FileToVector("data.txt", ":", S2, false, "").identity());
String S3 = "";
System.out.println(new FileVector("data.txt", ":", S3, false, null).identity());
}
}
[0,(0,a,c) (0,1,3) (0,azerty,cvf) (0,s)][4,(0,a,c) (0,1,3) (0,azerty,cvf),[5]]
[0,(0,a:b:c:d:e) (0,1 :2 : 3: 4: 5) (0,azerty : 1 : cvf : fff: qqqq) (0,s)]
[0,(0,a:b:c:d:e) (0,1 :2 : 3: 4: 5) (0,azerty : 1 : cvf : fff: qqqq) (0,s)]
[0,(0,a,b,c,d,e) (0,1,2,3,4,5) (0,azerty,1,cvf,fff,qqqq) (0,s)]
[0,(0,a,b,c,d,e) (0,1,2,3,4,5) (0,# comment) (0,azerty,1,cvf,fff,qqqq) (0,s)]
[0,(0,a,b,c,d,e) (0,1,2,3,4,5) (0,# comment) (0,azerty,1,cvf,fff,qqqq) (0,s)]
- We will convert the string sChampsVoulus into an array of integers tChampVoulus to bring it back to the case of the previous constructor.