Go红队开发—文件操作
文件操作
由于在上一期编解码中对文件有操作需求,所以这一期补上文件操作功能.
依旧是直接放代码,加速学习进度,代码拿着就用即可,都是内置的功能函数。
PS:一些函数参数或者功能解释都放在代码注释里面了
创建目录
// 创建目录
func createDir() {
err := os.Mkdir("test_dir", os.ModePerm)
if err != nil {
fmt.Println("创建目录失败")
return
}
fmt.Println("创建目录成功")
}
创建文件
// 创建文件
func createFile(filename string) {
newfile, err := os.Create(filename)
defer newfile.Close()
if err != nil {
fmt.Println("创建文件失败:", err)
return
}
fmt.Println("创建文件成功:", newfile.Name())
}
获取File信息
文件与目录都能判断
func getFileInfo() {
//path := "test_dir"
path := "test.txt"
fileInfo, err := os.Stat(path)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("文件名:", fileInfo.Name())
fmt.Println("文件大小:", fileInfo.Size())
fmt.Println("文件权限:", fileInfo.Mode())
fmt.Println("最后一次修改时间:", fileInfo.ModTime())
fmt.Println("是否为目录: ", fileInfo.IsDir())
//fmt.Println("系统接口类型: %T", fileInfo.Sys())
//fmt.Println("系统信息: %+v", fileInfo.Sys())
}
文件重命名
// 文件重命名
func renameFile() {
oldFileName := "text.txt"
newFileName := "newtest.txt"
err := os.Rename(oldFileName, newFileName)
if err != nil {
fmt.Println("重命名出错:", err)
return
}
}
删除文件
// 删除文件
func removeFile(fileaName string) {
err := os.Remove(fileaName)
if err != nil {
fmt.Println("删除失败:", err)
return
}
fmt.Println(fileaName, "删除成功")
}
打开关闭文件
// 打开关闭文件
// 介绍原始open打开文件与OpenFile可以提供更多的选项打开文件
func open_close_file() {
fmt.Println("os.Open打开文件")
file, err := os.Open("test.txt")
defer file.Close() //延迟关闭文件,建议打开文件后都习惯性写一个
if err != nil {
fmt.Println("os.Open打开文件失败:", err)
return
}
fmt.Println("os.Open文件打开成功")
//---------------------------------------------
fmt.Println("os.OpenFile打开文件")
file, err = os.OpenFile("test.txt", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
defer file.Close()
if err != nil {
fmt.Println("os.OpenFile打开文件失败:", err)
return
}
fmt.Println("os.OpenFile打开文件成功")
}
判断文件是否存在
// 判断文件是否存在
func isExistFile(fileName string) {
_, err := os.Stat(fileName)
if err != nil {
//因为报出错误可能有很多种原因,想要知道是不是文件不存在导致的err还需要验证
if os.IsNotExist(err) {
fmt.Println("确认这个错误是文件不存在导致的:", err)
}
}
}
判断文件是否有读取权限
// 判断文件是否有读写权限
func isPermission() {
file, err := os.OpenFile("test.txt", os.O_RDONLY, 0666) //直接给O_WRONLY标志,可以判断是否有写权限
defer file.Close()
if err != nil {
if os.IsPermission(err) {
fmt.Println("没有读取权限:", err)
}
}
fmt.Println("可读")
file, err = os.OpenFile("test.txt", os.O_WRONLY, 0666) //直接给O_WRONLY标志,可以判断是否有写权限
defer file.Close()
if err != nil {
if os.IsPermission(err) {
fmt.Println("没有写权限", err)
}
}
fmt.Println("可写")
}
复制文件
// 文件复制
func copyFile() {
//打开一个你要复制的文件
src_file, src_err := os.Open("test.txt")
defer src_file.Close()
if src_err != nil {
fmt.Println("文件打开失败:", src_err)
}
//创建一个新文件用来复制内容到这里(其实可以用存在的文件继续打开也行,主要是用file句柄而已)
des_file, des_err := os.Create("newtest.txt")
defer des_file.Close()
if des_err != nil {
fmt.Println("文件创建失败", des_err)
}
//复制内容到新文件中
bytesWritten, err := io.Copy(des_file, src_file) //bytesWritten是计算复制的长度
if err != nil {
fmt.Println("复制失败:", err)
}
fmt.Println("写入了:", bytesWritten)
// 将文件内容flush到硬盘中,这操作对于我们现在来说是不必要的,
// 因为在大多数情况下,程序正常退出时,数据会被操作系统自动刷新到磁盘。
// 当我们在不断地写入内容的时候可能就需要不定期的进行flush
err = des_file.Sync()
}
Read读取
// ---------------------------------------------------
// 读取文件内容
// ---------------------------------------------------
// Read读取文件内容,返回读取的长度和内容,如果读取的长度小于切片的长度,说明文件读取完了
func readFile() {
//打开文件
file, err := os.OpenFile("test.txt", os.O_RDWR, 0666)
defer file.Close()
if err != nil {
fmt.Println("打开文件失败:", err)
return
}
bytes_content := make([]byte, 10) //Read就是传进内容到这个切片空间中
contentlen, err := file.Read(bytes_content) //返回的是读取的长度
if err != nil {
fmt.Println("读取文件失败:", err)
return
}
fmt.Printf("读取长度:%d\n", contentlen)
fmt.Println("读取内容:", string(bytes_content))
}
ReadFull读取
// ReadFull读取文件内容,返回读取的长度和内容,如果读取的长度小于切片的长度会返回错误
func readFullFile() {
//打开文件
file, err := os.OpenFile("test.txt", os.O_RDWR, 0666)
defer file.Close()
if err != nil {
fmt.Println("打开文件失败:", err)
return
}
//ReadFull就是传进内容到这个bytes_content切片空间中,如果给的空间大于读取的内容就会报错,小于的的话给多少读多少
bytes_content := make([]byte, 2)
contentlen, err := io.ReadFull(file, bytes_content) //返回的是读取的长度
if err != nil {
fmt.Println("读取文件失败:", err)
return
}
fmt.Printf("读取长度:%d\n", contentlen)
fmt.Println("读取内容:", string(bytes_content))
}
ReadAtLeast读取
// ReadAtLeast至少读取xx bytes文件内容
func readAtLeastFile() {
//打开文件
file, err := os.OpenFile("test.txt", os.O_RDWR, 0666)
defer file.Close()
if err != nil {
fmt.Println("打开文件失败:", err)
return
}
bytes_content := make([]byte, 512) //Read就是传进内容到这个切片空间中
// io.ReadAtLeast()在拿不到最小的字节内容的时候会返回错误,
// 如果你不return回去,
// 他会把已读的文件保留。你依旧能够打印读取到的内容
//相比ReadFull,ReadAtLeast不会报错,
// 只是说最小字节数是至少读取这么多,
// 但是依旧会往后读取,报错会留下已读取的内容
minBytes := 10
contentlen, err := io.ReadAtLeast(file, bytes_content, minBytes) //返回的是读取的长度
if err != nil {
fmt.Println("读取文件失败:", err)
//return //取消return,依旧能打印读取到的内容
}
fmt.Printf("读取长度:%d\n", contentlen)
fmt.Println("读取内容:", string(bytes_content))
}
ReadAll读取
// ReadAll读取文件所有内容
func readAllFile() {
//打开文件
file, err := os.OpenFile("test.txt", os.O_RDWR, 0666)
defer file.Close()
if err != nil {
fmt.Println("打开文件失败:", err)
return
}
// io.ReadAll()会读取所有的文件内容,返回的是读取的长度
content, err := io.ReadAll(file) //返回的是读取的长度
if err != nil {
fmt.Println("读取文件失败:", err)
return
}
fmt.Println("读取内容:", string(content))
}
bufio读取
以下是 bufio.Scanner 中几种常用分割符的具体说明和示例:
bufio.ScanWords
- 分割符: 空格(
)或连续的空白字符(包括空格、制表符\t、换行符\n等)。 - 行为: 每次扫描一个单词(以空白字符分隔的字符串)。
- 示例:
scanner.Split(bufio.ScanWords)
输入:
"Hello World\nGo Programming"
输出:
"Hello"
"World"
"Go"
"Programming"
bufio.ScanLines
- 分割符: 换行符(
\n)。 - 行为: 每次扫描一行(以换行符分隔的字符串)。
- 示例:
scanner.Split(bufio.ScanLines)
输入:
"Hello\nWorld\nGo Programming"
输出:
"Hello"
"World"
"Go Programming"
bufio.ScanBytes
- 分割符: 无(按字节分割)。
- 行为: 每次扫描一个字节。
- 示例:
scanner.Split(bufio.ScanBytes)
输入:
"Hello"
输出:
'H'
'e'
'l'
'l'
'o'
bufio.ScanRunes
- 分割符: 无(按字符分割)。
- 行为: 每次扫描一个字符(支持多字节字符,如中文)。
- 示例:
scanner.Split(bufio.ScanRunes)
输入:
"你好,世界!"
输出:
'你'
'好'
','
'世'
'界'
'!'
总结
| 分割函数 | 分割符 | 行为 | 示例输入 | 示例输出 |
|---|---|---|---|---|
bufio.ScanWords |
空格( )或连续空白字符 |
每次扫描一个单词 | "Hello World\nGo" |
"Hello", "World", "Go" |
bufio.ScanLines |
换行符(\n) |
每次扫描一行 | "Hello\nWorld\nGo" |
"Hello", "World", "Go" |
bufio.ScanBytes |
无 | 每次扫描一个字节 | "Hello" |
'H', 'e', 'l', 'l', 'o' |
bufio.ScanRunes |
无 | 每次扫描一个字符(支持多字节字符) | "你好,世界!" |
'你', '好', ',', '世', '界', '!' |
注意事项
bufio.ScanWords:- 会忽略连续的空白字符(如多个空格或制表符)。
- 适合处理以空格分隔的文本。
bufio.ScanLines:- 会保留每行的内容(包括行尾的空白字符)。
- 适合处理逐行文本。
bufio.ScanBytes:- 按字节分割,适合处理二进制数据或需要逐字节分析的场景。
bufio.ScanRunes:- 按字符分割,支持多字节字符(如中文、日文、韩文等)。
- 适合处理 Unicode 文本。
示例代码:
// bufio读取文件能够配合scanner一行一行读取,安全开发过程中可能用的最多,因为爆破的需求一般都是一行一行读取
func bufioReadFile() {
//打开文件
file, err := os.OpenFile("test.txt", os.O_RDWR, 0666)
defer file.Close()
if err != nil {
fmt.Println("打开文件失败:", err)
return
}
//bufio.NewReader()返回一个io.Reader对象,可以用来读取文件内容
reader := io.Reader(file)
//bufio.NewScanner()返回一个io.Scanner对象,可以用来读取文件内容
scanner := bufio.NewScanner(reader)
//scanner.Split(bufio.ScanWords) //按照空格分割
//scanner.Split(bufio.ScanLines) //按照换行符分割 默认不写就是按照换行符分割
//scanner.Split(bufio.ScanBytes) //按照字节分割
//scanner.Split(bufio.ScanRunes) //按照字符分割
for scanner.Scan() {
fmt.Println(scanner.Text())
}
}
Write写入
// ---------------------------------------------------
// 写入文件内容
// ---------------------------------------------------
func write() {
file, err := os.OpenFile(
"test.txt",
os.O_CREATE|os.O_APPEND|os.O_RDWR|os.O_APPEND,
0666,
)
defer file.Close()
if err != nil {
fmt.Println("文件打开失败:", err)
return
}
bytesWrittenLen, err := file.Write([]byte("hello hack\n"))
if err != nil {
fmt.Println("内容写入失败:", err)
return
}
fmt.Printf("写入成功:%d字节长度\n", bytesWrittenLen)
}
WriteFile快速写入
// 快速写内容
// 用在需要快速简洁写入内容的时候
func ioutil_WriteFile() {
err := ioutil.WriteFile("test.txt", []byte("hello hack2\n"), 0666)
if err != nil {
fmt.Println("内容写入失败:", err)
return
}
}
临时文件目录
// 临时文件和目录,在开发工具的时候可能会用的上
func tmpDir_File() {
// 第一个参数是空字符串表示TempDir 会使用系统的默认临时目录。
// 在 Linux/macOS 上,通常是 /tmp。
// 在 Windows 上,通常是 C:\Users\<User>\AppData\Local\Temp。
tempDir, err := ioutil.TempDir("", "tmpDirName")
if err != nil {
fmt.Println("创建失败:", err)
return
}
fmt.Println("目录创建成功:", tempDir)
tempFile, err := ioutil.TempFile(tempDir, "temp.txt") //创建文件要给参数:tempDir目录和temp文件名字
if err != nil {
fmt.Println("文件创建失败:", err)
return
}
fmt.Println("文件创建成功:", tempFile.Name())
//虽然说是临时文件也耀手动关闭文件
defer tempFile.Close()
err = os.Remove(tempFile.Name())
if err != nil {
fmt.Println("文件删除失败")
return
}
err = os.Remove(tempDir)
if err != nil {
fmt.Println("目录删除失败")
return
}
}
下载文件
// http get downLoad文件到本地
func downLoadFile() {
httpFile, err := os.OpenFile(
"baidu.html",
os.O_CREATE|os.O_RDWR,
0666,
)
if err != nil {
fmt.Println("文件打开失败")
}
defer httpFile.Close()
url := "http://www.baidu.com"
rep, err := http.Get(url)
defer rep.Body.Close()
written, err := io.Copy(httpFile, rep.Body)
if err != nil {
fmt.Println("文件复制失败:", err)
}
fmt.Println("下载成功,文件大小(byte):\n", written)
}
文件指针操作
func offsetFile() {
//打开文件
file, err := os.OpenFile("test.txt", os.O_RDWR, 0666)
defer file.Close()
if err != nil {
fmt.Println("打开文件失败:", err)
return
}
//获取文件的偏移量
var (
offset int64 = 1
whence int = 1
//whence用来计算offset的位置
// 0 = 文件开始位置
// 1 = 当前位置
// 2 = 文件结尾处
)
newP, err := file.Seek(offset, whence)
if err != nil {
fmt.Println("获取文件偏移量失败:", err)
return
}
fmt.Println("文件偏移量:", newP)
//直接当前位置读取文件内容
bytes_content := make([]byte, 10) //Read就是传进内容到这个切片空间中
contentlen, err := file.Read(bytes_content) //返回的是读取的长度
if err != nil {
fmt.Println("读取文件失败:", err)
return
}
fmt.Printf("读取长度:%d\n", contentlen)
fmt.Println("读取内容:", string(bytes_content))
}
修改文件权限/拥有者/时间戳
参考文章:https://colobu.com/2016/10/12/go-file-operations/
这篇文章作者写的这真的很好,全是干货。
package main
import (
"log"
"os"
"time"
)
func main() {
// 使用Linux风格改变文件权限
err := os.Chmod("test.txt", 0777)
if err != nil {
log.Println(err)
}
// 改变文件所有者
err = os.Chown("test.txt", os.Getuid(), os.Getgid())
if err != nil {
log.Println(err)
}
// 改变时间戳
twoDaysFromNow := time.Now().Add(48 * time.Hour)
lastAccessTime := twoDaysFromNow
lastModifyTime := twoDaysFromNow
err = os.Chtimes("test.txt", lastAccessTime, lastModifyTime)
if err != nil {
log.Println(err)
}
}
知识细节补充
OS.OpenFile
先介绍一下这个openfile功能,之前我是使用os.open来打开文件, 但是只能以只读的方式打开文件,而openfile更通用的文件打开函数,可以指定打开模式(只读、只写、读写等)和文件权限。接下来我都会使用openfile来操作文件,更精细化控制文件。
⽂件打开模式标志,在使用openfile的时候需要以一个怎样的模式打开文件
比如:os.OpenFile("example.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
多个形式可以用|管道符分开,表示可读可写,同时CREATE表示当文件不存在的时候创建,同时APPEND表示追加模式。
更多模式可以看下面介绍
os.O_RDONLY:只读模式打开⽂件。
os.O_WRONLY:只写模式打开⽂件。
os.O_RDWR:读写模式打开⽂件。
os.O_APPEND:追加模式。如果⽂件已存在,数据将写⼊⽂件末尾。
os.O_CREATE:如果⽂件不存在,则创建⽂件。
os.O_EXCL:与 os.O_CREATE ⼀起使⽤,⽂件必须不存在。
os.O_SYNC:同步 I/O,保证写⼊数据和元数据同步到存储设备。
os.O_TRUNC:如果⽂件已存在,打开时将其⻓度截断为零。
细节写在前头:我们读取完或者写入完后,文件指针是不在开头的,如果你读取完就直接写入就是在你读取到的当前位置写入,或者你写入完成后继续读取就是在当前位置读取,可能读取不到你想要的内容,所以file.Seek就很有必要了,或者你重新打开该文件也可以自动将指针指向开头。
演示代码:
打开一个文件写入hello hack,然后读取这个文件内容
O_RDWR:可读可写O_CREATE:文件不存在就创建O_APPEND:追加模式- 最后的0666是文件操作权限,这里就涉及到linux的文件权限问题了(忽略,后面讲)
func write_readTest() {
file, err := os.OpenFile("test.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
defer file.Close()
if err != nil {
fmt.Println(err)
return
}
file.WriteString("hello hack") // 写入文件
// 读取文件
scanner := bufio.NewScanner(file)
//读取完文件后,文件指针已经到了文件末尾,需要重新定位到文件开头
// 将文件指针重新定位到文件开头
file.Seek(0, 0)
for scanner.Scan() {
fmt.Println(scanner.Text()) //一行一行读取
}
if err := scanner.Err(); err != nil {
fmt.Println("读取文件失败:", err)
}
}
bufio
我们在编解码的时候就用了这个bufio,我们可以new一个scanner来一行一行读取文件内容,如果你需要更细粒度的控制(如按字节读取),可以使用 bufio.Reader。
//常用方法
file, err := os.OpenFile("test.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
// 读取文件
scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text()) //一行一行读取
}
if err := scanner.Err(); err != nil {
fmt.Println("读取文件失败:", err)
}
os.Stat
os.Stat 是 Go 语言中用于获取文件或目录信息的函数。它的作用是返回一个描述文件或目录状态的对象(os.FileInfo)
参数
name:接受一个字符串参数,表示文件或目录的路径。
可以是相对路径(如
"../example.txt 或者目录 ../dirname")或绝对路径(如"/home/user/example.txt")。也可以是文件名(如果文件在当前工作目录下)。
返回值:
FileInfo: 一个接口类型,包含文件或目录的详细信息。error: 如果操作失败(如文件不存在),返回错误信息。
os.fileInfo
os.FileInfo 是一个接口,包含以下方法:
| 方法名 | 返回值类型 | 说明 |
|---|---|---|
Name() string |
string |
返回文件或目录的名称(不包括路径)。 |
Size() int64 |
int64 |
返回文件的字节大小(目录通常返回 0)。 |
Mode() FileMode |
FileMode |
返回文件的权限和模式。 |
ModTime() time.Time |
time.Time |
返回文件的最后修改时间。 |
IsDir() bool |
bool |
判断是否是目录。 |
Sys() interface{} |
interface{} |
返回底层数据源(通常为 nil)。 |
文件权限
使用⼋进制数表示⽂件的权限,这里是linux文件权限管理的知识,不懂自查。
os.ModePerm:⽂件的默认权限(0777)
os.ModeDir:表示⼀个⽬录。
os.ModeAppend:表示⽂件只能追加写⼊。
os.ModeExclusive:表示⽂件是独占的。
os.ModeTemporary:表示⽂件是临时⽂件。
os.ModeSymlink:表示⽂件是⼀个符号链接。
os.ModeDevice:表示⽂件是⼀个设备⽂件。
os.ModeNamedPipe:表示⽂件是⼀个命名管道。
os.ModeSocket:表示⽂件是⼀个 Unix 域套接字。
os.ModeSetuid:表示⽂件具有 setuid 位。
os.ModeSetgid:表示⽂件具有 setgid 位。
os.ModeCharDevice:表示⽂件是⼀个字符设备。
os.ModeSticky:表示⽂件具有粘滞位。
os.ModeIrregular:表示⽂件是⼀个不规则⽂件。
参考文章:https://colobu.com/2016/10/12/go-file-operations
Go红队开发—文件操作的更多相关文章
- IOS 开发文件操作——NSFileManager
转自:http://blog.csdn.net/xyz_lmn/article/details/8968213,留着方便查阅 iOS的沙盒机制,应用只能访问自己应用目录下的文件.iOS不像androi ...
- iOS开发-文件操作
目录操作和文件管理 学习目标 1.理解单例 2.掌握NSFileManager类常用的文件管理操 3.掌握NSFileHandle类常用的文件数据操作 4.了解NSData类的常用操作 5.掌握Pli ...
- Python开发 文件操作
阅读目录 1.读写文件 open()将会返回一个file对象,基本语法: open(filename,mode) filename:是一个包含了访问的文件名称的路径字符串 mode:决定了打开文件的模 ...
- Python开发——文件操作
文件的读取 http://www.cnblogs.com/linhaifeng/articles/5984922.html
- ASP.NET文件操作
在开发Web程序时,不但有存储在数据库中和XML文件中的数据形式需要处理,而且还有很多诸如文本.Word文档和图片等格式的文件数据需要处理.尤其是在一些信息管理系统中,文档的处理流程贯穿了整个系统的运 ...
- Android开发 ---如何操作资源目录中的资源文件2
Android开发 ---如何操作资源目录中的资源文件2 一.颜色资源管理 效果图: 描述: 1.改变字体的背景颜色 2.改变字体颜色 3.改变按钮颜色 4.图像颜色切换 操作描述: 点击(1)中的颜 ...
- 让你提前知道软件开发(22):shell脚本文件操作
文章1部分 再了解C语言 shell脚本中的文件操作 [文章摘要] 编写shell脚本时,经常会涉及到对文件的操作,比方从文件里读取一行数据.向文件追加一行数据等. 完毕文件读写操作的方法有非常多,了 ...
- loadrunner 脚本开发-文件读写操作
脚本开发-文件读写操作 by:授客 QQ:1033553122 函数说明 函数原型: size_t fwrite( const void *buffer, size_t size, size_t co ...
- Android开发---如何操作资源目录中的资源文件4 ---访问xml的配置资源文件的内容
Android开发---如何操作资源目录中的资源文件4 XML,位于res/xml/,这些静态的XML文件用于保存程序的数据和结构. XmlPullParser可以用于解释xml文件 效果图: 描述: ...
- Android开发---如何操作资源目录中的资源文件3--圆角边框、背景颜色渐变效果、边框颜色
Android开发---如何操作资源目录中的资源文件3 效果图 1.圆角边框 2.背景颜色渐变效果 1.activity_main.xml 描述: 定义了一个shape资源管理按钮 <?xml ...
随机推荐
- Vscode实现应用qss样式表
qss简介 qss(Qt Style Sheets)是一种基于CSS的样式语言,用于描述用户界面元素的外观和感觉.qss可以让用户在不修改代码的情况下,轻松地自定义应用程序的外观. 其语法基本如下: ...
- IM开发基础知识补课(十):大型IM系统有多难?万字长文,搞懂异地多活!
本文由公众号"水滴与银弹"号主Kaito原创分享,原题"搞懂异地多活,看这篇就够了",为使文章更好理解,有修订. 1.引言 前几天技术群里有群友问我手上有没有I ...
- 《深入理解Mybatis原理》MyBatis初始化机制详解
主要构件及其相互关系 主要构件: 主要的核心部件解释如下: SqlSession: 作为MyBatis工作的主要顶层API,表示和数据库交互的会话,完成必要数据库增删改查功能 Executor:MyB ...
- golang自带的死锁检测并非银弹
网上总是能看到有人说go自带了死锁检测,只要有死锁发生runtime就能检测到并及时报错退出,因此go不会被死锁问题困扰. 这说明了口口相传知识的有效性是日常值得怀疑的,同时也再一次证明了没有银弹这句 ...
- Python在多个Excel文件中找出缺失数据行数多的文件
本文介绍基于Python语言,针对一个文件夹下大量的Excel表格文件,基于其中每一个文件内.某一列数据的特征,对其加以筛选,并将符合要求与不符合要求的文件分别复制到另外两个新的文件夹中的方法. ...
- Solution Set - “我献上明月一盏,照满河山”
目录 0.「集训队互测 2018」「洛谷 P9248」完美的集合 1.「UR #6」「UOJ #74」破解密码 2.「NOI Simu.」苯为 3.「NOI Simu.」西克 4.「NOI Simu. ...
- CDS标准视图:技术对象类别文本 I_TechnicalObjectTypeText
视图名称:技术对象类别文本 I_TechnicalObjectTypeText 视图类型:基础 视图代码: 点击查看代码 @EndUserText.label: 'Technical Object T ...
- Android性能测试(内存、cpu、fps、流量、GPU、电量)——adb篇
adb 常用命令 获取连接设备号:adb devices 列出设备所有已安装的包名 (不需root权限) adb shell "pm list packages",可以加上 ...
- python实现excel数据处理
python xlrd读取excel(表格)详解 安装: pip install xlrd 官网地址: https://xlrd.readthedocs.io/ 介绍: 为开发人员提供一个库,用于从M ...
- Java注意事项
阅读目录 一.Comparable简介 二.Comparator简介 三.Comparable和Comparator区别比较 一.Comparable简介 Comparable是排序接口.若一个类实现 ...