题目描述 汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!
方法一:字符串截取
public class Solution {
public String LeftRotateString(String str,int n) {
int length = str.length();
if(length==0){
return "";
}
str += str;
n = n % length;
return str.substring(n, length+n);
}
}
方法二:字符串拼接
public class Solution {
public String LeftRotateString(String str,int n) {
if(str.length()==0)
return str;
int t = str.length();
if(n>t){
n%=t;
}
String s1 = str.substring(0,n);
String s2 = str.substring(n,t);
return s2+s1;
}
}
方法三:字符串反转
public class LeftRotateString {
public static void main(String[] args) {
System.out.println(leftRotateString("abcXYZdef", 3));
}
public static String leftRotateString(String str, int n) {
char[] strArray = str.toCharArray();
int len = str.length();
reverse(strArray,0,n-1); //反转前n个字符,得到cbaXYZdef
reverse(strArray,n,len-1); //反转第n个字符后面所有的字符cbafedZYX
reverse(strArray,0,len-1); //反转整个字符串XYZdefabc
System.out.println(Arrays.toString(strArray));
return str;
}
private static void reverse(char[] strArray, int begin, int end){
while(begin < end){
char temp = strArray[begin];
strArray[end] = strArray[begin];
strArray[begin] = temp;
begin ++;
end --;
}
}
}
FileChannel按行读取大文件
FileChannel是什么?
-
它是用于读取、写入、映射和操作文件的通道。除了熟悉的字节通道读取,写入和关闭操作之外,此类还定义了以下特定于文件的操作:
-
可以以不影响通道当前位置的方式在文件中的绝对位置读取或写入字节。
-
文件的区域可以直接映射到内存中。 对于大文件,这通常比调用通常的读取或写入方法要有效得多。
-
对文件所做的更新可能会被强制发送到基础存储设备,以确保在系统崩溃时不会丢失数据。
-
字节可以从文件传输到其他通道,反之亦然,可以通过许多操作系统进行优化,将字节快速传输到文件系统缓存或直接从文件系统缓存传输。
-
文件的区域可能被锁定,以防止其他程序访问。
-
FileChannel配合着ByteBuffer,将读写的数据缓存到内存中,然后以批量/缓存的方式read/write,省去了非批量操作时的重复中间操作,操纵大文件时可以显著提高效率。ByteBuffer可以使用直接内存(系统内存)(allocateDirect),使用后无需jvm回收。
总结一下,按照字节读取,对大文件读取效率更高,无法设置为非阻塞模式,它总是运行在阻塞模式下。
但有时候我们要按照行读取文件,而FileChannel只能按照字节读取,所以这里需要对换行进行判断一下,在这里我对其进行了实现,供大家参考。
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class test1 {
public static void readLineByChannel(String path) throws IOException {
long lineNumber = 0;
FileInputStream fileIn = new FileInputStream(path);
FileChannel fileChannel = fileIn.getChannel();
// 开始按行读取
int bufferSize = 1024 * 1024; // 每一块的大小
ByteBuffer buffer = ByteBuffer.allocate(bufferSize);
byte b;
while(fileChannel.read(buffer) > 0)
{
buffer.flip();
for (int i = 0; i < buffer.limit(); i++)
{
b = buffer.get();
if(b==10){ // 如果遇到换行
lineNumber++;
}
}
buffer.clear(); // 清空buffer
}
fileChannel.close();
System.out.println(lineNumber);
}
public static void readLineByBufferedReader(String path) throws IOException {
long lineNumber = 0;
FileInputStream inputStream = new FileInputStream(path);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while((line=bufferedReader.readLine()) != null)
{
lineNumber++;
}
inputStream.close();
bufferedReader.close();
System.out.println(lineNumber);
}
public static void main(String[] args) throws IOException {
String path = "大文件";
long startTime = System.currentTimeMillis();
readLineByChannel(path);
System.out.println("readLineByChannel耗时:" + (System.currentTimeMillis() - startTime));
startTime = System.currentTimeMillis();
readLineByBufferedReader(path);
System.out.println("readLineByBufferedReader耗时:" + (System.currentTimeMillis() - startTime));
}
}
使用FileChannel和BufferedReader分别的对大文件进行读取,并且计算有多少行。
//第一次测试:
169860474
readLineByChannel耗时:27310
169860474
readLineByBufferedReader耗时:24944
//第二次测试
169860474
readLineByChannel耗时:28677
169860474
readLineByBufferedReader耗时:21229
测试文件12GB,可以看出文件有1亿6千多万行,实际测试下来两者差距不大,甚至BufferedReader还快点。
文件按行倒序输出
perl -e 'print reverse <>' filename