[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[问题求助] poweshell 合并不同编码文本

本帖最后由 娜美 于 2024-5-8 21:57 编辑

需要将不同编码文本合并,有ANSI  UTF8  带BOM UTF8   有UTF16LE  UTF16BE  Unix和dis格式的

文件夹下有很多文本,大概有3000个,将需要合并的1000多文件名称已经写进一个b.txt文本内了,只需要按b.txt内文件名先后顺序合并即可,防止文本前后行串接,在拼接处,需要留空一行。出来后的文本为ANSI编码,

合并过程中,如果产生识别不了文件名的或者没有此文件啥的原因。需要返回一个提示没有此文件的名称,失败名称存放在另一个文本中bug.txt

由于有不同编码文本,所以优先考虑用poweshell 来完成,代码最好是简单性能又快又准确又帅
谢谢各位poweshell大哥哥啦

基本模型构想
  1. #@&cls&powershell "type %~s0|out-string|iex"&pause
  2. $text = "b.txt"
  3. $out = "all.tmp"
  4. $FailName =bug.txt
  5. #读取b.txt内名称顺序列表
  6. Get-Content  $txt
  7. # 合并
  8. Get-Content $text.FullName | Add-Content $out
  9. # 失败的文件名称
  10. Get-Content $FailName
复制代码

1.txt
a
b
c

3.txt
d
e

2.txt
f
g


#  按b.txt 名单顺序先后次序合并,   名单长这样, 名称中文也有一些符号
1.txt
3.txt
2.txt


#  如果产生识别不了文件名的或者没有此文件啥的原因, 需写入报告
bug.txt
2.txt

#  将它们合并后样式
all.tmp
a
b
c

d
e

f
g

回复 38# aloha20200628


   噢,真晕呀,我竟然没注意到这个,可能试多了晕了吧。好了,追求得到完满结束,多谢大哥哥哈

TOP

回复 37# 娜美

37楼代码第8行改为下行即可...
  1. powershell " gc '%%~F' -readcount 1000 -enc 'unicode'|ac 'allinOne.txt' "
复制代码

TOP

本帖最后由 娜美 于 2024-5-15 23:32 编辑

回复 36# aloha20200628
大哥哥32楼那个可以了
大哥哥请看看  套进这个里面 似乎返回一些错误
  1. @echo off &setlocal &del /q "allinOne.txt" "bug.txt" 2>nul
  2. for /f "delims=" %%F in (b.txt) do if not exist "%%~F" (echo,"badFile -- %%F"&echo,%%F>>"bug.txt") else (
  3. for /f "tokens=1-2 delims=-" %%a in (' uchardet.exe "%%~F" ') do (
  4. if /i "%%a" neq "unknown" (echo, /// %%~F ///>>"allinOne.txt")
  5. if /i "%%a"=="utf" if "%%b"=="8" (
  6. powershell " gc '%%~F' -readcount 1000 -enc 'utf8'|ac 'allinOne.txt' "
  7. ) else if /i "%%a"=="utf" if "%%b"=="16" (
  8. powershell " gc '%%~F' -readcount 1000 -enc 'utf16'|ac 'allinOne.txt' "
  9. )
  10. if /i "%%a"=="ascii" (
  11. powershell " gc '%%~F' -readcount 1000 -enc 'ascii'|ac 'allinOne.txt' "
  12. ) else if /i "%%a"=="gb18030" (
  13. powershell " gc '%%~F' -readcount 1000 -enc 'default'|ac 'allinOne.txt' "
  14. ) else if /i "%%a"=="unknown" (
  15. echo,"unknown -- %%F"&echo,%%F>>"bug.txt"
  16. )
  17. )
  18. echo,>>"allinOne.txt"
  19. )
  20. endlocal&pause&exit/b
复制代码
  1. Get-Content : 无法绑定参数“Encoding”。无法将值“utf16”转换为类型“Microsoft.PowerShell.Commands.FileSystemCmdletProviderEncoding”。错误:“无法将标识符名称 utf16 与有效的枚举器名称相匹配。请指定以下枚举器名称之一,然后重试:
  2. Unknown, String, Unicode, Byte, BigEndianUnicode, UTF8, UTF7, UTF32, Ascii, Default, Oem, BigEndianUTF32”
  3. 所在位置 行:1 字符: 47
  4. +  gc 'UTF16BE-UNIX编码.txt' -readcount 1000 -enc 'utf16'|ac 'allinOne.tx ...
  5. +                                               ~~~~~~~
  6.     + CategoryInfo          : InvalidArgument: (:) [Get-Content],ParameterBindingException
  7.     + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.GetContentCommand
复制代码

TOP

回复 35# 娜美

用以下5行代码替换32楼代码中的5-9行,再试吧...
  1. if /i "%%a"=="utf-8" (
  2. powershell " gc '%%~F' readcount 1000 -enc 'utf8'|ac 'allinOne.txt' "
  3. ) else if /i "%%a"=="utf-16" (
  4. powershell " gc '%%~F' readcount 1000 -enc 'unicode'|ac 'allinOne.txt' "
  5. ) else if /i "%%a"=="ansi" (powershell " gc '%%~F' readcount 1000|ac 'allinOne.txt' ")
复制代码

TOP

本帖最后由 娜美 于 2024-5-15 21:13 编辑

回复 34# aloha20200628

[io:file] 依靠内存模式
虽然也快  但抑制不了内存挤满问题




[io:file] 逐行读取模式   
速度4mb/s左右


速度30mb/s左右, 肯定是最快最佳方案,  但是代码套不进去
powershell "gc *.txt -readcount 1000 -enc:'default' | ac -enc:default 'all.tmp'"

另外more 也有些问题,要弃用, 大一点100mb文件会卡住不动

-- More (0%) --

TOP

回复 33# 娜美

为何从[io:file]高效方法回退管道模式呢

TOP

本帖最后由 娜美 于 2024-5-15 19:53 编辑

回复 32# aloha20200628

有问题,  只合并了ANSI编码文本,  UTF8  UTF16编码文本一个都没有被合并进去
似乎是这2 powershell写法原因

powershell "$s=gc '%%~F' readcount 1000 -enc 'utf8';ac 'allinOne.txt' $s"
powershell "$s=gc '%%~F' readcount 1000 -enc 'unicode';ac 'allinOne.txt' $s"


似乎是读取变量文件和ac问题
$s=gc '%%~F' readcount 1000

TOP

本帖最后由 aloha20200628 于 2024-5-15 17:28 编辑

回复 31# 娜美

管道是效率大杀器尤其是对大数据,尽量不用...
  1. @echo off &setlocal &del /q "allinOne.txt" "bug.txt" 2>nul
  2. for /f "delims=" %%F in (b.txt) do if not exist "%%~F" (echo,"badFile -- %%F"&echo,%%F>>"bug.txt") else (
  3. for /f "tokens=1 delims=_" %%a in (' coder.exe -s -a gc -f "%%~F" ') do (
  4. echo, /// %%~F ///>>"allinOne.txt"
  5. if /i "%%a"=="utf-8" (
  6. powershell "$s=gc '%%~F' readcount 1000 -enc 'utf8';ac 'allinOne.txt' $s"
  7. ) else if /i "%%a"=="utf-16" (
  8. powershell "$s=gc '%%~F' readcount 1000 -enc 'unicode';ac 'allinOne.txt' $s"
  9. ) else if /i "%%a"=="ansi" (more "%%~F">>"allinOne.txt")
  10. )
  11. echo,>>"allinOne.txt"
  12. )
  13. endlocal&pause&exit/b
复制代码

TOP

本帖最后由 娜美 于 2024-5-15 16:35 编辑

回复 30# aloha20200628
  1. powershell "gc *.txt -readcount 1000 -enc 'utf8'|ac 'all.tmp'"
复制代码
我套不进去,   脑壳不够用

TOP

回复 29# 娜美

顺便提一句》有人实测过,设置 -readcount 1000 的效果极佳
  1. powershell "gc *.txt -readcount 1000 -enc 'utf8'|ac 'all.tmp'"
复制代码

TOP

本帖最后由 娜美 于 2024-5-15 16:22 编辑

回复 28# aloha20200628


   大哥哥写了一个用gc的  单测它可以达到30mb/s


  返回错误,  我是不是变量没写好 ?  请帮看看
  1. @echo off &setlocal &del /q "allinOne.txt" "bug.txt" 2>nul
  2. for /f "delims=" %%F in (b.txt) do if not exist "%%~F" (echo,"badFile -- %%F"&echo,%%F>>"bug.txt") else (
  3. for /f "tokens=1 delims=_" %%a in (' coder.exe -s -a gc -f "%%~F" ') do (
  4. echo, /// %%~F ///>>"allinOne.txt"
  5. if /i "%%a"=="utf-8" (
  6. powershell "$a=gc -readcount 10000000 -enc:UTF8 "%%~F" | ac -enc:default all.tmp"
  7. ) else if /i "%%a"=="utf-16" (
  8. powershell "$a=gc -readcount 10000000 -enc:UTF16 "%%~F" | ac -enc:default all.tmp"
  9. ) else if /i "%%a"=="ansi" (
  10. powershell "$a=gc -readcount 10000000 -enc:default "%%~F" | ac -enc:default all.tmp"
  11. )
  12. )
  13. echo,>>"allinOne.txt"
  14. )
  15. endlocal&pause&exit/b
复制代码

TOP

回复 27# 娜美

用你的各种实例测试比对,即可一目了然了 也许老东家对很容易拖后腿的 ‘逐行读取’ 给予了 ‘特别关照’...

TOP

本帖最后由 娜美 于 2024-5-14 10:09 编辑

回复 26# aloha20200628
  1. powershell "$g=[text.encoding]::getEncoding('gb2312');$m=new-object io.streamWriter('allinOne.txt',$true,$g);foreach($l in [io.file]::readLines('%%~F',[text.encoding]::'utf8')){$m.writeLine($l)};$m.close()"
复制代码
poweshell 逐行读写速度是每秒 4Mb/s 左右。大哥哥 这是不是poweshell最快的写法了 ?

TOP

本帖最后由 aloha20200628 于 2024-5-13 22:32 编辑

回复 20# 娜美

‘一次性读写’ 改为 ‘逐行读写’ 方案》以便应付超大数据文件,不过还是采用了powershell中相当高效的[io.file]readLines/streamWriter
基于3楼代码改写如下,再试试吧...
  1. @echo off &setlocal &del /q "allinOne.txt" "bug.txt" 2>nul
  2. for /f "delims=" %%F in (b.txt) do if not exist "%%~F" (echo,"badFile -- %%F"&echo,%%F>>"bug.txt") else (
  3. for /f "tokens=1-2 delims=-" %%a in (' uchardet.exe "%%~F" ') do (
  4. if /i "%%a" neq "unknown" (echo, /// %%~F ///>>"allinOne.txt")
  5. if /i "%%a"=="utf" if "%%b"=="8" (
  6. powershell "$g=[text.encoding]::getEncoding('gb2312');$m=new-object io.streamWriter('allinOne.txt',$true,$g);foreach($l in [io.file]::readLines('%%~F',[text.encoding]::'utf8')){$m.writeLine($l)};$m.close()"
  7. ) else if /i "%%a"=="utf" if "%%b"=="16" (
  8. powershell "$g=[text.encoding]::getEncoding('gb2312');$m=new-object io.streamWriter('allinOne.txt',$true,$g);foreach($l in [io.file]::readLines('%%~F',[text.encoding]::'unicode')){$m.writeLine($l)};$m.close()"
  9. )
  10. if /i "%%a"=="ascii" (
  11. more "%%~F">>"allinOne.txt"
  12. ) else if /i "%%a"=="gb18030" (
  13. more "%%~F">>"allinOne.txt"
  14. ) else if /i "%%a"=="unknown" (
  15. echo,"unknown -- %%F"&echo,%%F>>"bug.txt"
  16. )
  17. )
  18. echo,>>"allinOne.txt"
  19. )
  20. endlocal&pause&exit/b
复制代码

TOP

返回列表