本程序编写于32位win7旗舰版,测试也是在这个系统下,欢迎朋友们提出修改意见。
功能:
显示指定文本文件的最后n行,支持自动读取及手动按回车读取。
格式说明:
tail <fileName> [-b <Number>] [-l <Number>] [-f <Number>]
标志说明:
-b <Number>
从末尾倒数 Number 表示的 512 字节块位置开始读取指定文件(无此参数则默认最后512字节),若要读取大量文本请将此值调大,例如:tail -b 10 filename.txt
-l <Number>
显示末尾Number行(无此参数则默认显示最后30行)
-f <Number>
每隔多少秒自动显示(无此参数则手动按回车显示下一次)
下面是调用例子:
tail -f 1 -b 2 -l 10 t.txt
每一秒自动显示一次(-f 1),最多从末尾读取512*2个字节(-b 2),从这些字节中读取最后10行(-l 10)
tail -b 2 -l 50 t.txt
最多从末尾读取512*2个字节(-b 2),从这些字节中读取最后50行(-l 50),手动按回车显示(省略[-f])
tail -b 2 t.txt
最多从末尾读取512*2个字节(-b 2),从这些字节中读取最后30行(省略[-l Number]默认读取最后30行),手动按回车显示(省略[-f])
#include <windows.h>
#include <iostream>
#include <fstream>
#include <string>
#include <malloc.h>
#include <stdlib.h>
using namespace std;
/**
* 格式说明:
* tail <fileName> [-b <Number>] [-l <Number>] [-f <Number>]
*
* 标志说明:
* -b <Number>
* 从末尾倒数 Number 表示的 512 字节块位置开始读取指定文件(无此参数则默认最后512字节)
* -l <Number>
* 显示末尾Number行(无此参数则默认显示最后30行)
* -f <Number>
* 每隔多少秒自动显示(无此参数则手动按回车显示下一次)
*
* 例:
* tail -f 1 -b 2 -l 10 t.txt
* 每一秒自动显示一次(-f 1),最多从末尾读取512*2个字节(-b 2),从这些字节中读取最后10行(-l 10)
*
* tail -b 2 -l 50 t.txt
* 最多从末尾读取512*2个字节(-b 2),从这些字节中读取最后50行(-l 50),手动按回车显示(省略[-f])
*
* tail -b 2 t.txt
* 最多从末尾读取512*2个字节(-b 2),从这些字节中读取最后30行(省略[-l Number]默认读取最后30行),手动按回车显示(省略[-f])
*/
// 检查字符数组的内容是否是标志
bool isFlag(char * charArr)
{
string temp = charArr;
if(charArr[0] == '-')
{
// 是以减号开头
if(temp!="-b" && temp!="-f" && temp!="-l")
{
// 非法标志
return false;
}
return true;
}
else
return false;
}
// 检查字符数组的内容是否是正整数,不是正整数则返回零
int isNum(char * charArr)
{
try
{
int v = atoi(charArr);
// 将当前参数转整数
if( atoi(charArr) < 1 )
return 0;
return v;
}
catch(...)
{
return 0;
}
}
/**
* 检查参数是否正确
* @param argc 一共有几个参数(从1开始)
* @param arg 用户输入的参数
*
* @return int (1:验证通过|-1:验证失败)
*/
int checkArg(int argc, char ** arg, int * b, int * l, int * f, char ** filename)
{
// 返回值
int ret = 1;
// 前一个参数是否是标志
bool preArgIsFlag = false;
// 是否已经读到文件名
bool readedFileName = false;
// 是否已经读到-b
bool readedB = false;
// 是否已经读到-l
bool readedL = false;
// 是否已经读到-f
bool readedF = false;
// 一维数组下标
int x = 0, v = 0;
string temp, temp1, temp2;
// 按元素个数从1开始循环
for(int i=1; i<argc; i++)
{
temp1 = arg[i];
if(i < argc-1)
{
temp2 = arg[i+1];
}
// 检查当前循环到的是不是最后一个元素
if(i < argc-1) // 如果当前循环到的不是最后一个元素
{
if(isFlag(arg[i])) // 如果当前元素是标志
{
if(!isFlag(arg[i+1])) // 如果下一个元素不是标志
{
// 如果当前元素是标志、下一个元素不是标志
v = isNum(arg[i+1]);
if(v < 1)
return 0;
if(temp1 == "-b")
{
if(readedB) // 如果已经读到-b则返加零
return 0;
*b = v;
readedB = true;
}
else if(temp1 == "-l")
{
if(readedL) // 如果已经读到-l则返加零
return 0;
*l = v;
readedL = true;
}
else if(temp1 == "-f")
{
if(readedF) // 如果已经读到-f则返加零
return 0;
*f = v;
readedF = true;
}else{ // 非法标志
return 0;
}
i++;
}
else // 如果下一个元素是标志
{
return 0;
}
}else{ // 如果当前元素不是标志则认定当前元素是文件名
if(readedFileName) // 如果已经读到文件名则返回零
return 0;
strcpy(*filename, arg[i]); // 修改传入参数中的文件名
readedFileName = true;
}
} // if(i < argc-1) // 如果当前循环到的不是最后一个元素
else // 如果当前循环到的是最后一个元素
{
if(isFlag(arg[i])){ // 如果当前元素是标志
return 0;
}
else // 如果当前元素不是标志
{
if(readedFileName) // 如果已经读到文件名则返回零
return 0;
strcpy(*filename, arg[i]); // 修改传入参数中的文件名
readedFileName = true;
}
}
} // for(int i=1; i<argc; i++)
if(!readedB) // 如果没有读到-b则赋默认值
{
*b = 1;
}
if(!readedL) // 如果没有读到-l则赋默认值
{
*l = 30;
}
if(!readedF) // 如果没有读到-f则赋默认值
{
*f = 0;
}
// 判断是否有文件名
if(!readedFileName)
return 0;
return ret;
}
int main(int argc, char ** argv)
{
//
int b; // 缓冲区大小(是几个512)
int l; // 要末尾读多少行
int f; // 每隔几秒自动显示
char * filename = new char[512];
// 检查参数是否正确
int result = checkArg(argc, argv, &b, &l, &f, &filename);
if(!result)
{
printf("出现错误,请参照以下说明修改命令参数:\n");
printf("格式说明:\n");
printf(" tail <fileName> [-b <Number>] [-l <Number>] [-f <Number>] \n");
printf(" 其中fileName最长512字节\n\n");
printf("标志说明:\n");
printf(" -b <Number>\n");
printf(" 从末尾倒数 Number 表示的 512 字节块位置开始读取指定文件(无此参数则默认最后512字节)\n");
printf(" -l <Number>\n");
printf(" 显示末尾Number行(无此参数则默认显示最后30行)\n");
printf(" -f <Number>\n");
printf(" 每隔多少秒自动显示(无此参数则手动按回车显示下一次)\n\n");
printf("例:\n");
printf(" tail -f 1 -b 2 -l 10 t.txt \n");
printf(" 每一秒自动显示一次(-f 1),最多从末尾读取512*2个字节(-b 2),从这些字节中读取最后10行(-l 10)\n\n");
printf(" tail -b 2 -l 50 t.txt\n");
printf(" 最多从末尾读取512*2个字节(-b 2),从这些字节中读取最后50行(-l 50),手动按回车显示(省略[-f])\n\n");
printf(" tail -b 2 t.txt\n");
printf(" 最多从末尾读取512*2个字节(-b 2),从这些字节中读取最后30行(省略[-l Number]默认读取最后30行),手动按回车显示(省略[-f])\n");
return 1;
}
// 要显示多少行
int showCount = l, showLineCount;
// 文件总大小
int count;
char * charArr;
while(true)
{
showLineCount = showCount;
ifstream ifs;
// 按二进制读取文本
ifs.open (filename, ios::binary);
if(ifs.fail())
{
cout<<"错误:文件不存在。"<<endl;
return 1;
}
// 将文件指针移动到末尾
ifs.seekg (0, ios::end);
// 读取文件总大小
count = ifs.tellg();
// 根据文件总大小计算应该读取多少字节
int shouldReadLength = (count>=512*b)?512*b:count;
// 按指定大小分配内存,加1是为了能在最后添加结束符'\0'
charArr = new char[shouldReadLength+1];
int i;
// 已读取字节数
int readed = 0;
// 将文件指针移动到距末尾-shouldReadLength个字节的位置
ifs.seekg (-shouldReadLength, ios::end);
// 读取指定大小的内容
ifs.read (charArr,shouldReadLength);
// 添加结束符
charArr[shouldReadLength] = '\0';
for(i=shouldReadLength-1; i>=0 && showLineCount>0; i--,readed++)
{
if(charArr[i] == '\n'){
showLineCount--;
}
}
// 输出
printf("%s\n", charArr + shouldReadLength - readed); // 这种方法可以输出到控制台
//cout.write (charArr + shouldReadLength - readed,readed);// 这种方法也可以输出到控制台
// 释放字符数组的内存空间
delete [] charArr;
// 关闭文件流
ifs.close();
if(f==0) // 用户没有输入-f参数,等待用户再次敲回车
{
// 如果用手动的就用cin---------- 开始
cout<<"按Ctrl+C退出或按回车继续:";
// 用户按回车时进行下一次显示
cin.get();
//system("PAUSE");
// 如果用手动的就用cin---------- 结束
}
else // 用户输入了-f参数,按用户输入的秒数睡眠
{
// 如果要自动的就用Sleep-------- 开始
Sleep(1000*f);
// 如果要自动的就用Sleep-------- 结束
}
}
return 0;
}
附件tail.rar中是exe可执行文件,下面是校验码:
大小: 66070 字节
修改时间: 2011年8月10日, 15:19:51
MD5: 0CAB365E4A42F83FDABAA5AB011DC0A9
SHA1: 3F0972645F15BA6DB8F70A7EF3F9C760607B684B
CRC32: 8F22B704
转载请注明出处
分享到:
相关推荐
在Windows操作系统中,"tail"命令通常用于查看文件的末尾部分,这在Linux系统中是一个常见的工具,但在Windows环境下并不内置。为了在Windows上实现类似的功能,我们可以使用一些第三方工具或者编写脚本来完成。标题...
它特别强调了"模仿Linux中的Tail",意味着它试图复制Linux `tail`命令的核心特性,使用户在Windows环境下也能享受到类似的使用体验。另外,该工具的源代码是使用Visual Studio 2015(VS 2015)编写的,这是一款由...
在Windows的CMD中实现Linux的`tail`功能,可以借助`more`命令的组合技巧,也可以使用专门为CMD设计的第三方工具,如提供的`tail.exe`。了解这些工具的工作原理和用途,对于提升系统管理和故障排查能力至关重要。在...
本篇将详细介绍一个简单的Linux驱动程序的编写过程,以及如何在CentOS Linux系统中成功加载和运行。 首先,我们需要一个开发环境。这里选择的是Windows 7 64位系统作为宿主机,通过VMware虚拟机安装CentOS Linux...
tail命令**:介绍了tail命令的使用场景。 - **9. grep命令**:说明了grep命令的功能。 - **10. chmod命令**:讲解了chmod命令的作用。 - **11. cp命令**:介绍了cp命令的用途。 - **12. mv命令**:解释了mv命令...
理解Linux命令行操作是有效管理服务器的关键,如使用`service`或`systemctl`控制服务状态,用`vi`或`nano`编辑配置文件,通过`chown`和`chmod`调整文件权限,以及利用`grep`、`tail`等命令查看和分析日志。...
`whereis` 命令与 `which` 类似,但是它可以同时查找命令的二进制文件、源码文件和手册页。 4. **locate** - **功能说明**:从数据库 (`/var/lib/mlocate/mlocate.db`) 查找命令,使用 `updatedb` 更新库。`locate`...
4、在nmap中输入自己主机windows的IP地址(也可在nmap文件中用命令扫描nmap -A ip);5、日志生成在 /var/log/syslog里面,用tail -f /var/log/syslog可实时检测文件内容。6可以查看下自己虚拟机的ip地址,进行完第...
在Windows系统中,`more`命令同样存在,但在PowerShell中,用户更常使用`Get-Content -Wait -Tail`命令来实现类似的功能。 `more`和`less`这两个工具的工作原理是通过读取标准输入(stdin)或指定文件的内容,然后...
在Linux下,开发内核模块涉及到对内核源码的理解,使用`make`命令编译模块,并通过`insmod`或`rmmod`命令加载或卸载模块。这些技能是Linux系统管理员和驱动开发者的基础。 至于LKM(Linux Kernel Module,Linux内核...
解决方案是在第39行将命令`tail +${SKIP}${SCRIPT}|gunzip|tarxvf-`改为`tail -n+${SKIP} ${SCRIPT}|gunzip|tarxvf–`。 - 同时,在脚本的最后一行添加一个空行。 3. **编译并运行Hello World程序**: - 使用`arm...
Linux系统日志记录在 `/var/log` 目录下,如`/var/log/syslog`和`/var/log/messages`。通过`less`或`tail`命令查看日志。 12. 故障排除 学会使用`dmesg`查看内核消息,`journalctl`(Systemd系统中)查阅系统日志,...
1. **Linux简介**:Linux是一种自由和开放源码的操作系统,其内核由林纳斯·托瓦兹创建,如今已发展成为全球范围内广泛使用的服务器平台。了解Linux的历史、哲学以及与其他操作系统(如Windows和macOS)的区别对于新...
在Windows环境下,首先确保已经安装了Python(推荐3.6或更高版本)和pip。打开命令提示符,输入以下命令来安装Prophet: ``` pip install fbprophet ``` 2. **macOS安装** 对于macOS用户,同样需要Python和pip...
Linux的树型结构,Linux的文本编辑,Linux的安装和启动,用户管理,Shell编程技术,进程管理,C编译器,系统扩充,维护与监视,Linux的图形界面,网络的基本概念与设置,Linux在网络资源共享和电子邮件方面的应用,...