IO流
- 15.1 File类
- 15.1.1 Flile
- 15.1.2 FileFilter接口
- 15.2 IO流
- 15.2.1 概念
- 15.2.2 流的分类
- 15.2.2.1 按方向
- 15.2.2.2 按单位
- 15.2.2.3 按功能
- 15.3 字节流【重点】
- 15.3.1 字节抽象类
- 15.3.2 文件字节流【重点】
- 15.3.3 IO流细节
- 15.3.4 字节缓冲流【重点】
- 15.3.5 综合案例(文件拷贝)
- 15.3.6 对象流【重点】
- 15.3.6.1 对象流读写基本类型
- 15.3.6.2 对象流读写对象
- 15.3.6.3 对象流读写集合
- 15.3.6.4 对象流使用细节
- 15.4 字符流【重点】
- 15.4.1 字符抽象类
- 15.4.2 文件字符流【重点】
- 15.4.3 字符缓冲流【重点】
- 15.4.4 转换流
- 15.4.5 打印流
- 15.5 字符编码【理解】
- 15.6 Properties实现流操作
15.1 File类
15.1.1 Flile
概念:表示操作系统磁盘上的文件或者是文件夹
路径:
- 相对路径 (相对于当前工程的跟路径)
- 绝对路径 (在磁盘上的完整路径)
常见方法
方法名 | 描述 |
---|---|
createNewFile() | 创建一个新文件。 |
mkdir() | 创建一个新目录。如果父目录不存在,则无法创建 |
mkdirs() | 创建一个新目录。如果父目录不存在,则一起创建 |
delete() | 删除文件或空目录。 |
exists() | 判断File对象所对象所代表的对象是否存在。 |
length() | 获取文件(夹)的大小(字节) |
getAbsolutePath() | 获取文件的绝对路径。 |
getAbsoluteFile() | 获取文件(夹)的绝对路径:(返回File) |
getName() | 获取当前file对象的文件名或者是文件夹名 |
getParent() | 获取当前file对象的父目录(返回String) |
isDirectory() | 是否是目录。 |
isFile() | 是否是文件。 |
getPath() | 获取文件(夹)的相对路径:(返回String) |
listFiles() | 列出目录中的所有内容。 |
案例演示:
public class TestFile {public static void main(String[] args) throws Exception {//separator();//fileOpe();directoryOpe();}//(1)分隔符public static void separator() {System.out.println("路径分隔符"+File.pathSeparator);System.out.println("名称分隔符"+File.separator);}//(2)文件操作public static void fileOpe() throws Exception {//1创建文件 createNewFile()File file=new File("d:\\file.txt");//System.out.println(file.toString());if(!file.exists()) {boolean b=file.createNewFile();System.out.println("创建结果:"+b);}//2删除文件//2.1直接删除//System.out.println("删除结果:"+file.delete());//2.2使用jvm退出时删除
// file.deleteOnExit();
// Thread.sleep(5000);//3获取文件信息System.out.println("获取文件的绝对路径:"+file.getAbsolutePath());System.out.println("获取路径:"+file.getPath());System.out.println("获取文件名称:"+file.getName());System.out.println("获取父目录:"+file.getParent());System.out.println("获取文件长度:"+file.length());System.out.println("文件创建时间:"+new Date(file.lastModified()).toLocaleString());//4判断System.out.println("是否可写:"+file.canWrite());System.out.println("是否时文件:"+file.isFile());System.out.println("是否隐藏:"+file.isHidden());}//(3)文件夹操作public static void directoryOpe() throws Exception{//1 创建文件夹File dir=new File("d:\\aaa\\bbb\\ccc");System.out.println(dir.toString());if(!dir.exists()) {//dir.mkdir();//只能创建单级目录System.out.println("创建结果:"+dir.mkdirs());//创建多级目录}//2 删除文件夹//2.1直接删除(注意删除空目录)//System.out.println("删除结果:"+dir.delete());//2.2使用jvm删除
// dir.deleteOnExit();
// Thread.sleep(5000);//3获取文件夹信息System.out.println("获取绝对路径:"+dir.getAbsolutePath());System.out.println("获取路径:"+dir.getPath());System.out.println("获取文件夹名称:"+dir.getName());System.out.println("获取父目录:"+dir.getParent());System.out.println("获取创建时间:"+new Date(dir.lastModified()).toLocaleString());//4判断System.out.println("是否时文件夹:"+dir.isDirectory());System.out.println("是否时隐藏:"+dir.isHidden());//5遍历文件夹File dir2=new File("d:\\图片");String[] files=dir2.list();System.out.println("--------------------------------");for (String string : files) {System.out.println(string);}}}
//创建File对象
File file = new File("d:\\a.txt");
if(!file.exists()) {//创建文件file.createNewFile();
}
System.out.println("判断文件或者是文件夹是否存在"+file.exists());
System.out.println("判断是否是文件:"+file.isFile());
System.out.println("判断是否是文件夹:"+file.isDirectory());
System.out.println("获取文件或者文件夹的名字:"+file.getName());
System.out.println("获取文件大小(字节):"+file.length());
System.out.println("获取文件的相对路径:"+file.getPath());
System.out.println("获取文件的绝对路径(String):"+file.getAbsolutePath());
System.out.println("获取文件的绝对路径(File):"+file.getAbsoluteFile());
System.out.println("获取文件的父目录(String):"+file.getParent());
System.out.println("获取文件的父目录(File):"+file.getParentFile());System.out.println("获取文件所在位置磁盘的总空间:"+file.getTotalSpace());
System.out.println("获取文件所在位置磁盘的可用空间:"+file.getFreeSpace());
System.out.println("获取文件的最后修改时间(毫秒)"+file.lastModified());
System.out.println("判断文件是否可读"+file.canRead());
System.out.println("判断文件是否可写"+file.canWrite());
System.out.println("判断文件是否可执行"+file.canExecute());
System.out.println("判断文件是否是隐藏文件"+file.isHidden());
15.1.2 FileFilter接口
FileFilter:文件过滤器接口
- boolean accept(File pathname)。
- 当调用File类中的listFiles()方法时,支持传入FileFilter接口接口实现类,对获取文件进行过滤,只有满足条件的文件的才可出现在listFiles()的返回值中。
案例演示:过滤所有的.jpg图片。
public class TestFileFilter{public static void main(String[] args){File dir=new File("d:\\图片");File[] files2=dir.listFiles(new FileFilter() {@Overridepublic boolean accept(File pathname) {if(pathname.getName().endsWith(".jpg")) {return true;}return false;}});for (File file : files2) {System.out.println(file.getName());}}
}
15.2 IO流
15.2.1 概念
- 内存与存储设备之间传输数据的通道。
- 水借助管道传输;数据借助流传输。
15.2.2 流的分类
15.2.2.1 按方向
- 输入流:将<存储设备>中的内容读入到<内存>中。
- 输出流:将<内存>中的内容写入到<存储设备>中。
15.2.2.2 按单位
- 字节流:以字节为单位,可以读写所有数据 。
- 字符流:以字符为单位,只能读写文本数据 。
15.2.2.3 按功能
- 节点流:具有实际传输数据的读写功能。
- 过滤流:在节点流的基础之上增强功能。
15.3 字节流【重点】
15.3.1 字节抽象类
InputStream
:字节输入流
- public int read(){}。
- public int read(byte[] b){}。
- public int read(byte[] b,int off,int len){}。
OutputStream
:字节输出流
- public void write(int n){}。
- public void write(byte[] b){}。
- public void write(byte[] b,int off,int len){}。
15.3.2 文件字节流【重点】
FileOutputStream
:
out.write(int b)
;
- 一次写入一个字节,整数表示这个字节对应ASCII码值
out.write(byte b)
;
- 一次写入一个字节数组的内容
out.write(b, off, len)
;
- 参数2:从数组的指定位置开始
- 参数3:执行写出的字节个数
- 一次写入一个字节数组的内容
FileInputStream
:
fis.read()
;
- 一次读取一个字节,返回这个字节所对应的ASCII值,如果读到流的末尾返回-1
fis.read(byte[] b)
;
- 从流中一次读取自定义缓冲区大小的字节,并返回读取到的字节长度,如果读到流的末尾返回-1
fis.read(byte[] b,int offset,int len)
;
- 参数2:读取到数组中指定起始位置
- 参数3: 指定读取的字节个数
- 从流中一次读取自定义缓冲区大小的字节,并返回读取到的字节长度,如果读到流的末尾返回-1
文件字节输入流
FileInputStream
public class FileInputStreamDemo {public static void main(String[] args) {FileInputStream fis = null;try {//一、创建流对象fis = new FileInputStream("a.txt");//二、通过流对象进行读或者写/** 方法1:read()* 一次读取一个字节,返回这个字节所对应的ASCII值,如果读到流的末尾返回-1*/
// System.out.println(fis.read());
// System.out.println(fis.read());
// System.out.println(fis.read());
// System.out.println(fis.read());/*** 方法2:fis.read(b)* 从流中一次读取自定义缓冲区大小的字节,并返回读取到的字节长度,如果读到流的末尾返回-1* *///自定义缓冲区
// byte[] buf = new byte[1024];
// int len = fis.read(buf);
// //将byte数组转换成String字符串
// String str = new String(buf,0,len);
// System.out.println(str);//自定义缓冲区
// byte[] buf = new byte[1024];
// int len;
// while( (len = fis.read(buf)) != -1) {
// String str = new String(buf,0,len);
// System.out.println(str);
// }/*** 方法3:fis.read(buf,offset,len);* 参数2:读取到数组中指定起始位置* 参数3: 指定读取的字节个数* * 从流中一次读取自定义缓冲区大小的字节,并返回读取到的字节长度,如果读到流的末尾返回-1*///自定义缓冲区byte[] buf = new byte[1024];fis.read(buf, 2, 3);System.out.println(Arrays.toString(buf)); } catch (Exception e) {e.printStackTrace();}finally {//三、关闭流对象try {if(fis != null)fis.close();} catch (IOException e) {e.printStackTrace();} } }
}
文件字节输入流
FileOutputStream
public class FileOutputStreamDemo {public static void main(String[] args) {//一、创建流对象FileOutputStream fos = null;try {fos = new FileOutputStream(new File("b.txt"));//二、通过流对象进行读或者写/*** fos.write(int b)* 一次写入一个字节,整数表示这个字节对应ASCII码值*///fos.write(97);/*** fos.write(byte[] b);* 一次写入一个字节数组的内容*///byte[] b = "你好".getBytes();//fos.write(b);/*** fos.write(byte[] b,int offset,int len);* 参数2:从数组的指定位置开始* 参数3:执行写出的字节个数* * 一次写入一个字节数组的内容*/byte[] b = "你好吗?".getBytes();//System.out.println(Arrays.toString(b));//fos.write(b, 2, 6);fos.write(b,0,b.length);} catch (Exception e) {e.printStackTrace();}finally {//三、关闭流对象try {if(fos != null)fos.close();} catch (IOException e) {e.printStackTrace();}} }
}
15.3.3 IO流细节
- 1、在使用文件输出流的时候如果文件不存在会自动创建,但是要保证其父目录存在
- 2、在使用文件输出流的时候,如果想要向文件中追加内容,那么需要将构造参数append设置为true
- 3、在使用IO读写的时候,读写的操作应当写在try代码块中,关闭资源的代码写在finally代码块中
- 4、将IO流的创建写在try()中,这样IO流在使用完成之后无需关闭
15.3.4 字节缓冲流【重点】
缓冲流:
BufferedOutputStream
/BufferedInputStream
- 提高IO效率,减少访问磁盘的次数。
- 数据存储在缓冲区中,flush是将缓存区的内容写入文件中,也可以直接close。
public class BufferedSteamDemo {public static void main(String[] args) throws Exception {
// //一、创建缓冲流流对象
// FileInputStream fis = new FileInputStream("c.txt");
// BufferedInputStream bis = new BufferedInputStream(fis);
//
// //二、通过流对象进行读写
// byte[] buf = new byte[1024];
// int len;
// while((len = bis.read(buf) ) != -1) {
// String str = new String(buf, 0, len);
// System.out.println(str);
// }
//
// //三、关闭流资源(后用先关闭)
// bis.close();
// fis.close();//一、创建缓冲流流对象FileOutputStream fos = new FileOutputStream("d.txt");BufferedOutputStream bos = new BufferedOutputStream(fos);//二、通过流对象进行读写bos.write("hello,缓冲流".getBytes());//刷新(将缓冲区的内容刷新到目的地(硬盘))bos.flush();//三、关闭流资源(后用先关闭)//关闭流资源的时候,会自动刷新缓冲区内容。(只会刷新一次)bos.close();fos.close(); }
}
15.3.5 综合案例(文件拷贝)
public class FileCopyDemo {public static void main(String[] args) {copy2();}public static void copy1() {long start = System.currentTimeMillis();FileInputStream fis = null;FileOutputStream fos = null;try {fis = new FileInputStream("C:\\Users\\hawa\\Desktop\\Java2105班\\上课视频\\1阶段.zip");fos = new FileOutputStream("d:\\1.zip");//定义缓冲区(一次读取1024个字节)byte[] buf = new byte[1024];int len;while((len = fis.read(buf)) != -1) {fos.write(buf,0,len);}} catch (Exception e) {e.printStackTrace();}finally {try {if(fis!=null)fis.close();if(fos!=null)fos.close();} catch (IOException e) {e.printStackTrace();}}long end = System.currentTimeMillis();//字节流耗时:147035System.out.println("字节流耗时:"+(end - start));}public static void copy2() {long start = System.currentTimeMillis();FileInputStream fis = null;BufferedInputStream bis = null;FileOutputStream fos = null;BufferedOutputStream bos = null;try {fis = new FileInputStream("C:\\Users\\hawa\\Desktop\\Java2105班\\上课视频\\1阶段.zip");fos = new FileOutputStream("d:\\1.zip");bis = new BufferedInputStream(fis,80*1024);bos = new BufferedOutputStream(fos,80*1024);byte[] buf = new byte[1024];int len;while((len = bis.read(buf)) !=-1) {bos.write(buf, 0, len);//刷新一次就相当于磁盘之间的一次IO操作,会降低效率//bos.flush();}} catch (Exception e) {e.printStackTrace();}finally {try {if(fis!=null)fis.close();if(bis != null) bis.close();if(bos!=null)bos.close();if(fos!=null)fos.close();} catch (IOException e) {e.printStackTrace();}}long end = System.currentTimeMillis();//缓冲流耗时:106388System.out.println("缓冲流耗时:"+(end - start));}
}
copy1()方法耗时147s
copy2()方法耗时17s
15.3.6 对象流【重点】
对象流:
ObjectOutputStream
/ObjectInputStream
- 增加了缓冲区功能。
- 增加了读写8种基本数据类型和字符串功能。
- 增加了读写对象的功能:
readObject()
从流中读取一个对象。writeObject(Object obj)
向流中写入一个对象
15.3.6.1 对象流读写基本类型
//============对象流读写基本类型+String类型============//一、创建流对象
FileOutputStream fos = new FileOutputStream("e.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
//二、通过对象流进行读写
oos.writeInt(97); //Integer
oos.writeDouble(100.25); //Double
oos.writeUTF("对象流"); //String
//三、关闭流资源
oos.close();
fos.close();//一、创建流对象
FileInputStream fis = new FileInputStream("e.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
//二、通过对象流进行读写 (读取的顺序和写入的顺序要一致)
System.out.println(ois.readInt());
System.out.println(ois.readDouble());
System.out.println(ois.readUTF());
//三、关闭流资源
ois.close();
fis.close();
15.3.6.2 对象流读写对象
对象流写操作(序列化)
//============对象流读写对象============//写入对象
FileOutputStream fos = new FileOutputStream("f.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);User user = new User("cxk", 30);
oos.writeObject(user);oos.close();
fos.close();
对象流写操作(反序列化)
//读取对象
FileInputStream fis = new FileInputStream("f.txt");
ObjectInputStream ois = new ObjectInputStream(fis);User user1 = (User) ois.readObject();
System.out.println(user1);ois.close();
fis.close();
实体类(必须要实现序列化接口)
class User implements Serializable{String name;int age;//.....
}
15.3.6.3 对象流读写集合
//============对象流读写List集合============
//写入对象
FileOutputStream fos = new FileOutputStream("f.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);User user1 = new User("cxk1", 31);
User user2 = new User("cxk2", 32);
User user3 = new User("cxk3", 33);
List<User> userList = new ArrayList<User>();
userList.add(user1);
userList.add(user2);
userList.add(user3);
oos.writeObject(userList);oos.close();
fos.close();//读取对象
FileInputStream fis = new FileInputStream("f.txt");
ObjectInputStream ois = new ObjectInputStream(fis);List<User> users = (List<User>) ois.readObject();
System.out.println(users);
List<User> users1 = (List<User>) ois.readObject();ois.close();
fis.close();
15.3.6.4 对象流使用细节
序列化的细节:
- 1、对象流读到流的末尾,会抛出异常
EOFException
- 2、如果属性不想被序列化,那么可以使用transient关键字修饰
- 3、类实现了
Serializable
接口,会自动生成一序列化id(序列化和反序列的id要保证一致)
15.4 字符流【重点】
15.4.1 字符抽象类
Reader
:字符输入流
- public int read(){}。
- public int read(char[] c){}。
- public int read(char[] b,int off,int len){}。
Writer
:字符输出流
- public void write(int n){}。
- public void write(String str){}。
- public void write(String str,int offset,int len){}。
- public void write(char[] c){}。
- public void write(char[] c,int offset,int len){}。
15.4.2 文件字符流【重点】
文件字符输入流
FileReader
public class FileReaderAndWriterDemo2 {public static void main(String[] args) throws Exception {//一、创建字符流对象FileReader fr = new FileReader("h.txt");//二、通过流对象读写数据/*** fr.read()* 一次读取一个字符,并返回这个字符在Unicode码表中的值,如果读到流的末尾返回-1*///System.out.println(fr.read());//System.out.println(fr.read());/*** fr.read(char[] ch)* 一次读取一个字符数组,并返回读取到的字符的长度,如果读到流的末尾返回-1*/
// char[] cbuf = new char[1024];
// int len;
// while((len = fr.read(cbuf)) != -1) {
// String str = new String(cbuf, 0, len);
// System.out.println(str);
// }/*** fr.read(char[] ch,int offset,int len)* 参数2:指定存放在数组中的起始位置 参数3:指定存放字符的长度* 一次读取一个字符数组,并返回读取到的字符的长度,如果读到流的末尾返回-1*/char[] cbuf = new char[1024];fr.read(cbuf, 3, 10);System.out.println(Arrays.toString(cbuf));//三、关闭流资源fr.close();}
}
文件字符输出流
FileWriter
public class FileReaderAndWriterDemo {public static void main(String[] args) throws Exception {//一、创建字符流对象FileWriter fw = new FileWriter("h.txt");//二、通过流对象读写数据/*** write(int b)* 写入一个字符,整数表示这个字符在Unicode码表中的值*///fw.write(97);//fw.write(20320);/*** write(char[] ch)* 写入一个字符数组*///String str = "你真棒";//fw.write(str.toCharArray());/*** write(String str)* 写入一个字符串*///fw.write("你好真棒!!!");/*** write(char[] ch,int offset,int len)* 参数2:可以指定数组的起始位置 参数3:可以指定写入的字符长度* 写入一个字符数组*///String str = "你真棒";//fw.write(str.toCharArray(), 1, 2);/*** write(String str)* 参数2:可以指定字符串的起始位置 参数3:可以指定写入的字符长度* 写入一个字符串*/fw.write("你好真棒!!!", 1, 2);//三、关闭流资源fw.close();}
}
15.4.3 字符缓冲流【重点】
缓冲流:
BufferedWriter
/BufferedReader
- 支持输入换行符
- 可一次写一行、读一行。
public class BufferedDemo {public static void main(String[] args) throws Exception {//1、创建字符串缓冲输入流BufferedReader br = new BufferedReader(new FileReader("d:\\a.txt"));//2、通过字符缓冲流读取内容//一次一行内容,读到文件末尾返回null//System.out.println(br.readLine());String line;while((line = br.readLine()) != null) {System.out.println(line);}//3、关闭资源br.close();//1、创建字符缓冲输出流BufferedWriter bw = new BufferedWriter(new FileWriter("d:\\ddd.txt"));bw.write("BufferedWriter。。。。。");//写入一个换行bw.newLine();bw.write("第二行。。。。。");//3、关闭资源bw.close();}
}
15.4.4 转换流
转换流:
InputStreamReader
/OutputStreamWriter
- 可将字节流转换为字符流。
- 可设置字符的编码方式。
将字节输入流转换成字符输入流,并设置编码
public class InputStreamReaderDemo {public static void main(String[] args) throws Exception {//1、创建字节流对象FileInputStream fis = new FileInputStream("d:\\a.txt");//2、将字节流装换成字符流InputStreamReader isr = new InputStreamReader(fis, "UTF-8");//3、将字符流包装成字符缓冲流BufferedReader br = new BufferedReader(isr);String line;while( (line = br.readLine()) != null) {System.out.println(line);}br.close();//OutputStreamWriter 将字节输出流转换成字符输出流}
}
15.4.5 打印流
- 字节打印流
- 字符打印流
打印流中提供了一组可以直接写出基本类型和String的方法
注意:打印流中的print(Object obj)方法并不是写出对象,而是写出对象的toString方法的返回值
public class PrintDemo {public static void main(String[] args) throws Exception {//1、创建字节打印流PrintStream ps = new PrintStream("D:\\aaaa.txt");//printXXX方法ps.print(10);//换行ps.println("dsadsa");ps.print("哈哈print流");//注意:写入的是对象字符串变现形式(toString方法的结果)ps.print(new Student());ps.close(); //2、创建字符打印流PrintWriter pw = new PrintWriter("D:\\aaaa.txt");pw.print("哈哈");pw.println();pw.print(1000);pw.close();}
}
15.5 字符编码【理解】
- 字符
- 各个国家的文化符号
- 字符集
- 将文化符号进行统一收集生成字符集合(字典)
- 字符编码
- 每一种字符集 对字符的编排
- 常见字符集 :
ASCII
、GBK
、Unicode
(万国码)- 常见的字符编码:
ASCII编码 GBK编码 UTF-8 UTF-16 UTF-32 ISO8859-1 Big5 GB2312 GB18030
ASCII编码
- 美国信息交换标准代码 最多只能表示256个字符
- 一个字符 = 一个字节
GBK编码
- 国标码 前身是
GB2312
- 如果是0~128 ASCII码中的字符 。 一个字符 = 一个字节
- 其他情况 一个字符 = 两个字节
UTF-8 编码
- 可变字符
- 如果是0~128 ASCII码中的字符 一个字符 = 一个字节
- 如果是128~2048 Unicode码表中的字符 一个字符 = 两个字节
- 如果是2048 ~65535 Unicode码表的字符 一个字符 = 三个字节
- 编码:
- 将程序的内容写入到目的地,就是编码过程
- 解码:
- 将目的地的内容读取到程序中,就是解码过程
- 为什么会出现乱码?
- 编码和解码的编码方式不一致
常见字符编码:
编码 | 说明 |
---|---|
ISO-8859-1 | 收录除ASCII外,还包括西欧、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号。 |
UTF-8 | 针对Unicode的可变长度字符编码。 |
GB2312 | 简体中文。 |
GBK | 简体中文、扩充。 |
BIG5 | 台湾,繁体中文。 |
注:当编码方式和解码方式不一致时,会出现乱码。
15.6 Properties实现流操作
Properties:属性集合。
特点:
- 存储属性名和属性值。
- 属性名和属性值都是字符串类型。
- 没有泛型。
- 和流有关。
案例演示:Properties实现流操作。
public class TestProperties {public static void main(String[] args) throws Exception {//1创建集合Properties properties=new Properties();//2添加数据properties.setProperty("username", "zhangsan");properties.setProperty("age", "20");System.out.println(properties.toString());//3遍历//3.1-----keySet----略//3.2-----entrySet----略//3.3-----stringPropertyNames()---Set<String> pronames=properties.stringPropertyNames();for (String pro : pronames) {System.out.println(pro+"====="+properties.getProperty(pro));}//4和流有关的方法//----------list方法---------PrintWriter pw=new PrintWriter("d:\\print.txt");properties.list(pw);pw.close();//----------2store方法 保存-----------FileOutputStream fos=new FileOutputStream("d:\\store.properties");properties.store(fos, "注释");fos.close();//----------3load方法 加载-------------Properties properties2=new Properties();FileInputStream fis=new FileInputStream("d:\\store.properties");properties2.load(fis);fis.close();System.out.println(properties2.toString());}
}