diff --git a/NDP461-KB3102436-x86-x64-AllOS-ENU.exe b/NDP461-KB3102436-x86-x64-AllOS-ENU.exe new file mode 100644 index 0000000000000000000000000000000000000000..cfa946e368aefea69720e326df05b4306d8495ae Binary files /dev/null and b/NDP461-KB3102436-x86-x64-AllOS-ENU.exe differ diff --git a/README.md b/README.md index 407f0479bfadc03aef7a575df39a9fe5e4db0fc7..cb5a7b652daed4f2252601569686f24bab851f23 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,8 @@ # 本地文本搜索定位器 -![主界面](images/MainWindow.png) -![区域管理](images/SearchAreaManagement.png) -![创建索引](images/BuildIndex.png) -![索引完成](images/BuildIndexFinish.png) -![自动分词](images/Keywords1.png) -![手动分词](images/Keywords2.png) -![类型筛选](images/FileFilter.png) -![搜索分页](images/Page.png) -![重建确认](images/RebuildIndexConfirm.png) -![清空按钮](images/Clean.png) -![热键设置](images/HotKey.png) +![封面](images/Cover.png) #### 软件介绍 -基于.net实现的本地文档的全文索引定位器,根据关键词搜索定位本地文档内容。便于查找历史文档时节省时间,本地文本搜索神器! +基于.net实现的本地文档的全文索引定位器,根据关键词搜索定位本地文档内容。便于查找历史文档时节省时间,本地文档全文搜索神器! #### 软件架构 本地单机软件。 @@ -21,10 +11,23 @@ * NPOI、Spire、Microsoft.Office实现的文档内容读取 #### 安装教程 -* 运行环境基于.net freamwork 4.6(需要安装此环境才能运行,win10+默认有此环境) +* 运行环境基于.net freamwork 4.6.1(需要安装此环境才能运行) * 发布版下载解压可用 #### 使用说明 +![主界面](images/MainWindow.png) +![区域管理](images/SearchAreaManagement.png) +![创建索引](images/BuildIndex.png) +![索引完成](images/BuildIndexFinish.png) +![自动分词](images/Keywords1.png) +![手动分词](images/Keywords2.png) +![类型筛选](images/FileFilter.png) +![搜索分页](images/Page.png) +![重建确认](images/RebuildIndexConfirm.png) +![清空按钮](images/Clean.png) +![热键设置](images/HotKey.png) +![参数设置](images/Setting.png) + 1. 双击文件夹设置自己需要搜索的文件夹 2. 点击“重建”按钮创建文档索引,更新文档索引点击“优化”按钮。 3. 索引创建结束后,搜索框输入关键词后,回车或者点击搜索按钮。搜索结果列表会显示搜索结果列表 @@ -48,6 +51,7 @@ 7. [Microsoft.Office.Interop.Word](https://www.nuget.org/packages/Microsoft.Office.Interop.Word/) 8. [Microsoft.Office.Interop.PowerPoint](https://www.nuget.org/packages/Microsoft.Office.Interop.PowerPoint/) 9. [Hardcodet.NotifyIcon.Wpf](https://www.nuget.org/packages/Hardcodet.NotifyIcon.Wpf/) +10. [SharpCompress](https://www.nuget.org/packages/SharpCompress) #### 仓库地址 * [github](https://github.com/liulei901112/TextLocator) diff --git a/TextLocator/App.config b/TextLocator/App.config index 4f874ae2920347fb5cea3eb41825a923c31dd37a..19d62a660cc0881a44d000747ee561eeb7f5b8ba 100644 --- a/TextLocator/App.config +++ b/TextLocator/App.config @@ -49,7 +49,7 @@ - + @@ -65,6 +65,10 @@ + + + + - \ No newline at end of file + diff --git a/TextLocator/App.xaml.cs b/TextLocator/App.xaml.cs index 50b6dee7a14bb72fd0b2186af0646edb44ab40af..aeec4417afc01cbddcdd1d41936bfc0a6756bf41 100644 --- a/TextLocator/App.xaml.cs +++ b/TextLocator/App.xaml.cs @@ -32,8 +32,9 @@ namespace TextLocator public App() { + // 初始化线程池大小 - InitThreadPoolSize(); + AppCore.SetThreadPoolSize(); // 初始化配置 InitAppConfig(); @@ -81,21 +82,6 @@ namespace TextLocator } #region 初始化 - /// - /// 初始化线程池大小 - /// - private void InitThreadPoolSize() - { - bool setMinThread = ThreadPool.SetMinThreads(AppConst.THREAD_POOL_MIN_SIZE, AppConst.THREAD_POOL_MIN_SIZE); - log.Debug("修改线程池最小线程数量:" + AppConst.THREAD_POOL_MIN_SIZE + " => " + setMinThread); - bool setMaxThread = ThreadPool.SetMaxThreads(AppConst.THREAD_POOL_MAX_SIZE, AppConst.THREAD_POOL_MAX_SIZE); - log.Debug("修改线程池最大线程数量:" + AppConst.THREAD_POOL_MAX_SIZE + " => " + setMaxThread); - - // 保存线程池 - AppUtil.WriteValue("ThreadPool", "MinSize", AppConst.THREAD_POOL_MIN_SIZE + ""); - AppUtil.WriteValue("ThreadPool", "MaxSize", AppConst.THREAD_POOL_MAX_SIZE + ""); - } - /// /// 初始化文件信息服务引擎 /// @@ -118,6 +104,7 @@ namespace TextLocator FileInfoServiceFactory.Register(FileType.图片, new NoTextFileService()); // 程序员服务 FileInfoServiceFactory.Register(FileType.代码, new DevelopFileService()); + FileInfoServiceFactory.Register(FileType.压缩包, new ZipFileService()); // 纯文本服务 FileInfoServiceFactory.Register(FileType.纯文本, new TxtFileService()); } @@ -132,7 +119,7 @@ namespace TextLocator /// private void InitAppConfig() { - // 保存线程池 + // 保存文件读取超时时间 AppUtil.WriteValue("AppConfig", "FileReadTimeout", AppConst.FILE_READ_TIMEOUT + ""); } #endregion diff --git a/TextLocator/Core/AppConst.cs b/TextLocator/Core/AppConst.cs index fa4a0cf6f11ccf172b98191c6d0702c3a92f3d9c..2851fb6376c7e7d6333f7d47acde71ff783c77ab 100644 --- a/TextLocator/Core/AppConst.cs +++ b/TextLocator/Core/AppConst.cs @@ -15,13 +15,31 @@ namespace TextLocator.Core /// /// 线程池最小数量 /// - public static readonly int THREAD_POOL_MIN_SIZE = int.Parse(AppUtil.ReadValue("ThreadPool", "MinSize", "32")); + public static int THREAD_POOL_MIN_SIZE = int.Parse(AppUtil.ReadValue("ThreadPool", "MinSize", "32")); /// /// 线程池最大数量 /// - public static readonly int THREAD_POOL_MAX_SIZE = int.Parse(AppUtil.ReadValue("ThreadPool", "MaxSize", "64")); + public static int THREAD_POOL_MAX_SIZE = int.Parse(AppUtil.ReadValue("ThreadPool", "MaxSize", "64")); /// - /// App.ini路径:_AppDir\\_AppName\\Index\\ + /// 结果列表分页条数 + /// + public static int MRESULT_LIST_PAGE_SIZE = int.Parse(AppUtil.ReadValue("AppConfig", "ResultListPageSize", "100")); + /// + /// 文件读取超时时间,单位:秒 + /// + public static int FILE_READ_TIMEOUT = int.Parse(AppUtil.ReadValue("AppConfig", "FileReadTimeout", "600")); + /// + /// 文件大小限制 + /// + public static int FILE_SIZE_LIMIT = int.Parse(AppUtil.ReadValue("AppConfig", "FileSizeLimit", "500000000")); + /// + /// 压缩包解析大小 + /// + public static int ZIP_FILE_SIZE_LIMIT = int.Parse(AppUtil.ReadValue("AppConfig", "ZipFileSizeLimit", "20000000")); + + + /// + /// 索引路径:_AppDir\\_AppName\\Index\\ /// public static readonly string APP_INDEX_DIR = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Index"); /// @@ -34,22 +52,13 @@ namespace TextLocator.Core /// 分割器 /// public static readonly JiebaSegmenter INDEX_SEGMENTER = new JiebaSegmenter(); - /// /// 索引写入初始化(FSDirectory表示索引存放在硬盘上,RAMDirectory表示放在内存上) /// 磁盘路径:Lucene.Net.Store.FSDirectory.Open(new DirectoryInfo(_AppIndexDir)) /// 内存:new Lucene.Net.Store.RAMDirectory() /// public static readonly Lucene.Net.Store.FSDirectory INDEX_DIRECTORY = Lucene.Net.Store.FSDirectory.Open(new DirectoryInfo(APP_INDEX_DIR)); - - /// - /// 搜索最大值限制 - /// - public static readonly int MAX_COUNT_LIMIT = int.Parse(AppUtil.ReadValue("AppConfig", "MaxCountLimit", "100")); - /// - /// 文件读取超时时间,单位:秒 - /// - public static readonly int FILE_READ_TIMEOUT = int.Parse(AppUtil.ReadValue("AppConfig", "FileReadTimeout", "600")); + /// /// 匹配特殊字符 @@ -76,6 +85,7 @@ namespace TextLocator.Core /// public static readonly Regex REGEX_START_WITH = new Regex(@"^(\`|\$|\~|\.)"); + /// /// 比例最小值 /// diff --git a/TextLocator/Core/AppCore.cs b/TextLocator/Core/AppCore.cs index b39190e785efb665e4bdab9049447d31c007540a..c8d9f2e7e307853c8b09c03c8e1e838a9aa27d5e 100644 --- a/TextLocator/Core/AppCore.cs +++ b/TextLocator/Core/AppCore.cs @@ -2,6 +2,8 @@ using System; using System.Diagnostics; using System.IO; +using System.Threading; +using TextLocator.Util; namespace TextLocator.Core { @@ -36,5 +38,20 @@ namespace TextLocator.Core Shutdown(); } + + /// + /// 设置线程池大小 + /// + public static void SetThreadPoolSize() + { + bool setMinThread = ThreadPool.SetMinThreads(AppConst.THREAD_POOL_MIN_SIZE, AppConst.THREAD_POOL_MIN_SIZE); + log.Debug("修改线程池最小线程数量:" + AppConst.THREAD_POOL_MIN_SIZE + " => " + setMinThread); + bool setMaxThread = ThreadPool.SetMaxThreads(AppConst.THREAD_POOL_MAX_SIZE, AppConst.THREAD_POOL_MAX_SIZE); + log.Debug("修改线程池最大线程数量:" + AppConst.THREAD_POOL_MAX_SIZE + " => " + setMaxThread); + + // 保存线程池 + AppUtil.WriteValue("ThreadPool", "MinSize", AppConst.THREAD_POOL_MIN_SIZE + ""); + AppUtil.WriteValue("ThreadPool", "MaxSize", AppConst.THREAD_POOL_MAX_SIZE + ""); + } } } diff --git a/TextLocator/Enums/FileType.cs b/TextLocator/Enums/FileType.cs index 6d8e42b65a136b656b0c9c868450373da290cbd9..48e6054276d688ee06844355a88d878a9b4d2d6e 100644 --- a/TextLocator/Enums/FileType.cs +++ b/TextLocator/Enums/FileType.cs @@ -43,6 +43,11 @@ namespace TextLocator.Enums [Description("cs,java,js,css,md,py,c,h,cpp,lua,sql,jsp,json,php,rs,rb,yml,yaml,bat,ps1")] 代码, /// + /// 压缩包 + /// + [Description("rar,zip,7z,tar,jar")] + 压缩包, + /// /// 纯文本 /// [Description("txt")] diff --git a/TextLocator/Exceptions/FileSizeTooBigException.cs b/TextLocator/Exceptions/FileSizeTooBigException.cs new file mode 100644 index 0000000000000000000000000000000000000000..0ad359135a6296b30aa03c024197a01ad18657f6 --- /dev/null +++ b/TextLocator/Exceptions/FileSizeTooBigException.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TextLocator.Exceptions +{ + /// + /// 文件太大 + /// + public class FileBigSizeException : IOException + { + public FileBigSizeException(string message) : base(message) + { + } + } +} diff --git a/TextLocator/Exceptions/NotFoundFileServiceException.cs b/TextLocator/Exceptions/NotFoundFileServiceException.cs new file mode 100644 index 0000000000000000000000000000000000000000..fe8466962ab365ca39f636e55b5a4f74251ebdb1 --- /dev/null +++ b/TextLocator/Exceptions/NotFoundFileServiceException.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TextLocator.Exceptions +{ + /// + /// 未找到文件服务 + /// + public class NotFoundFileServiceException : Exception + { public NotFoundFileServiceException(string message) : base(message) + { + } + } +} diff --git a/TextLocator/Factory/FileInfoServiceFactory.cs b/TextLocator/Factory/FileInfoServiceFactory.cs index 9464f368ddde8641f73456b604916a4ac8858a96..b29ceb635b003dafb15c6e7cb2c763641f55dfaf 100644 --- a/TextLocator/Factory/FileInfoServiceFactory.cs +++ b/TextLocator/Factory/FileInfoServiceFactory.cs @@ -1,10 +1,12 @@ using log4net; using System; using System.Collections.Generic; +using System.IO; using System.Threading; using System.Threading.Tasks; using TextLocator.Core; using TextLocator.Enums; +using TextLocator.Exceptions; using TextLocator.Service; using TextLocator.Util; @@ -30,13 +32,32 @@ namespace TextLocator.Factory /// public static string GetFileContent(string filePath) { + FileInfo fileInfo = new FileInfo(filePath); + try + { + // 如果文件存在 + if (fileInfo == null && !fileInfo.Exists) + { + throw new FileNotFoundException("文件未找到,请确认"); + } + // 文件太大 + if (fileInfo.Length > AppConst.FILE_SIZE_LIMIT) + { + throw new FileBigSizeException("不支持大于 " + FileUtil.GetFileSizeFriendly(AppConst.FILE_SIZE_LIMIT) + " 的文件解析"); + } + } + catch (Exception ex) + { + log.Error(filePath + "->" + ex.Message, ex); + + return null; + } + // 获取文件服务对象 IFileInfoService fileInfoService = GetFileInfoService(FileTypeUtil.GetFileType(filePath)); - string content; // 读取文件内容 - content = WaitTimeout(fileInfoService.GetFileContent, filePath, TimeSpan.FromSeconds(AppConst.FILE_READ_TIMEOUT)); - return content; + return WaitTimeout(fileInfoService.GetFileContent, filePath, TimeSpan.FromSeconds(AppConst.FILE_READ_TIMEOUT)); } /// @@ -64,7 +85,7 @@ namespace TextLocator.Factory catch (Exception ex) { log.Error(ex.Message, ex); - throw new Exception("暂无[" + fileType.ToString() + "]服务实例, 返回默认其他类型文件服务实例"); + throw new NotFoundFileServiceException("暂无[" + fileType.ToString() + "]服务实例, 返回默认其他类型文件服务实例"); } } #endregion diff --git a/TextLocator/MainWindow.xaml.cs b/TextLocator/MainWindow.xaml.cs index 5568a2e07eaa0c6bdb5778cae50fb86199c1564b..0749b09b5cb2f8c13bf35620df4f998ea6dccbc0 100644 --- a/TextLocator/MainWindow.xaml.cs +++ b/TextLocator/MainWindow.xaml.cs @@ -124,9 +124,9 @@ namespace TextLocator CleanSearchResult(); // 检查配置参数信息 - if (string.IsNullOrEmpty(AppUtil.ReadValue("AppConfig", "MaxCountLimit", ""))) + if (string.IsNullOrEmpty(AppUtil.ReadValue("AppConfig", "ResultListPageSize", ""))) { - AppUtil.WriteValue("AppConfig", "MaxCountLimit", AppConst.MAX_COUNT_LIMIT + ""); + AppUtil.WriteValue("AppConfig", "ResultListPageSize", AppConst.MRESULT_LIST_PAGE_SIZE + ""); } // 检查索引是否存在:如果存在才执行更新检查,不存在的跳过更新检查。 @@ -571,7 +571,7 @@ namespace TextLocator // 查询数据分页 - Lucene.Net.Search.TopFieldDocs topDocs = searcher.Search(boolQuery, null, pageNow * pageSize, sort); + Lucene.Net.Search.TopFieldDocs topDocs = searcher.Search(boolQuery, null, pageNow * PageSize, sort); // 结果数组 Lucene.Net.Search.ScoreDoc[] scores = topDocs.ScoreDocs; @@ -581,7 +581,7 @@ namespace TextLocator // 设置分页标签总条数 this.Dispatcher.BeginInvoke(new Action(() => { // 如果总条数小于等于分页条数,则不显示分页 - this.PageBar.Total = totalHits > pageSize ? totalHits : 0; + this.PageBar.Total = totalHits > PageSize ? totalHits : 0; // 上一个和下一个切换面板是否显示 this.SwitchPreview.Visibility = totalHits > 0 ? Visibility.Visible : Visibility.Hidden; @@ -604,8 +604,8 @@ namespace TextLocator Entity.FileInfo fileInfo; // 计算显示数据 - int start = (pageNow - 1) * pageSize; - int end = pageSize * pageNow; + int start = (pageNow - 1) * PageSize; + int end = PageSize * pageNow; if (end > totalHits) end = totalHits; // 获取并显示列表 for (int i = start; i < end; i++) @@ -700,15 +700,14 @@ namespace TextLocator /// /// 每页显示数量 /// - public int pageSize = AppConst.MAX_COUNT_LIMIT; public int PageSize { // 获取值时将私有字段传出; - get { return pageSize; } + get { return AppConst.MRESULT_LIST_PAGE_SIZE; } set { // 赋值时将值传给私有字段 - pageSize = value; + AppConst.MRESULT_LIST_PAGE_SIZE = value; // 一旦执行了赋值操作说明其值被修改了,则立马通过INotifyPropertyChanged接口告诉UI(IntValue)被修改了 OnPropertyChanged("PageSize"); } @@ -1161,26 +1160,35 @@ namespace TextLocator { log.Debug("目录:" + s); // 获取文件信息列表 - FileUtil.GetAllFiles(filePaths, _regexExclusionFolder, s); + FileUtil.GetAllFiles(filePaths, s, _regexExclusionFolder); } log.Debug("GetFiles 耗时:" + fileMark.ConsumeTime + "秒"); ShowStatus("文件扫描完成,开始" + tips + "索引..."); + // 验证扫描文件列表是否为空 + if (filePaths == null || filePaths.Count <= 0) + { + build = false; + + ShowStatus("就绪"); + + Dispatcher.BeginInvoke(new Action(() => + { + Message.ShowWarning("MessageContainer", "未找到可以需要索引的文档"); + })); + + return; + } + // 排重 filePaths = filePaths.Distinct().ToList(); // 排序 - filePaths = ListUtil.Shuffle(filePaths); + filePaths = ListUtil.Shuffle(filePaths); // 创建索引方法 IndexCore.CreateIndex(filePaths, rebuild, ShowStatus); - /*// 索引拷贝前删除 - FileUtil.RemoveDirectory(AppConst.APP_INDEX_DIR); - - // 索引拷贝:索引创建结束后拷贝新索引覆盖旧的索引,并删除write.lock - FileUtil.CopyDirectory(AppConst.APP_INDEX_BUILD_DIR, AppConst.APP_INDEX_DIR);*/ - string msg = "索引" + tips + "完成。共用时:" + taskMark.ConsumeTime + "秒"; // 显示状态 diff --git a/TextLocator/NotifyIcon/NotifyIconViewModel.cs b/TextLocator/NotifyIcon/NotifyIconViewModel.cs index 7779237fe733c2c9a2d0cf642597d218bcbbfcb5..24f5d548a4767cff562ad0070df50c2e39809876 100644 --- a/TextLocator/NotifyIcon/NotifyIconViewModel.cs +++ b/TextLocator/NotifyIcon/NotifyIconViewModel.cs @@ -32,7 +32,7 @@ namespace TextLocator.NotifyIcon } /// - /// 系统设置 + /// 热键设置 /// public ICommand ShowHotKeyWindowCommand { @@ -55,6 +55,32 @@ namespace TextLocator.NotifyIcon }; } } + + /// + /// 系统设置 + /// + public ICommand ShowSettingWindowCommand + { + get + { + return new DelegateCommand + { + CommandAction = () => + { + var win = SettingWindow.CreateInstance(); + if (!win.IsVisible) + { + win.ShowDialog(); + } + else + { + win.Activate(); + } + } + }; + } + } + /// /// 隐藏窗口 diff --git a/TextLocator/Properties/AssemblyInfo.cs b/TextLocator/Properties/AssemblyInfo.cs index 93deef0f125d064b40cc4164e484c5c23d3b2fe1..2385d32ce66350e9b1860e06ddc86f7707b6a429 100644 --- a/TextLocator/Properties/AssemblyInfo.cs +++ b/TextLocator/Properties/AssemblyInfo.cs @@ -49,8 +49,8 @@ using System.Windows; //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 //通过使用 "*",如下所示: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.2.7")] -[assembly: AssemblyFileVersion("1.2.7.0")] +[assembly: AssemblyVersion("1.2.10")] +[assembly: AssemblyFileVersion("1.2.10.0")] // log4net [assembly: log4net.Config.XmlConfigurator(Watch = true)] \ No newline at end of file diff --git a/TextLocator/Properties/Resources.Designer.cs b/TextLocator/Properties/Resources.Designer.cs index bf5f86dcc3382dc6193d14a967ff32d3fd4a30e6..8d0eb41802278040dcd81492a7f443a681e4af7c 100644 --- a/TextLocator/Properties/Resources.Designer.cs +++ b/TextLocator/Properties/Resources.Designer.cs @@ -19,7 +19,7 @@ namespace TextLocator.Properties { // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen // (以 /str 作为命令选项),或重新生成 VS 项目。 - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -149,5 +149,15 @@ namespace TextLocator.Properties { return ((System.Drawing.Bitmap)(obj)); } } + + /// + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 + /// + internal static System.Drawing.Bitmap zip { + get { + object obj = ResourceManager.GetObject("zip", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } } } diff --git a/TextLocator/Properties/Resources.resx b/TextLocator/Properties/Resources.resx index 54491892d3363721a359496324f24d2d41661772..dea23c55097141bc17264ec1d18bdf86f3a5f411 100644 --- a/TextLocator/Properties/Resources.resx +++ b/TextLocator/Properties/Resources.resx @@ -145,4 +145,7 @@ ..\Resource\ext\word.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\resource\ext\zip.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/TextLocator/Properties/Settings.Designer.cs b/TextLocator/Properties/Settings.Designer.cs index 4c26443db472c1b672b8f6140c105e6f11b5a06e..237b9e10ac1d6db022f9d6526e1bce9697abae47 100644 --- a/TextLocator/Properties/Settings.Designer.cs +++ b/TextLocator/Properties/Settings.Designer.cs @@ -1,27 +1,24 @@ //------------------------------------------------------------------------------ // -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 // //------------------------------------------------------------------------------ - -namespace TextLocator.Properties -{ +namespace TextLocator.Properties { + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase - { - + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.1.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default - { - get - { + + public static Settings Default { + get { return defaultInstance; } } diff --git a/TextLocator/Resource/GenericDictionary.xaml b/TextLocator/Resource/GenericDictionary.xaml index 9c01ac55eab653cf7b6bf526c1f6cc32552c2410..1fa8c07c566e5dd399cfb46e13e165023217b959 100644 --- a/TextLocator/Resource/GenericDictionary.xaml +++ b/TextLocator/Resource/GenericDictionary.xaml @@ -14,6 +14,7 @@ + diff --git a/TextLocator/Resource/ext/zip.png b/TextLocator/Resource/ext/zip.png new file mode 100644 index 0000000000000000000000000000000000000000..74293b96be4a9901e7d6c52dc60d0b2a0fdfcf41 Binary files /dev/null and b/TextLocator/Resource/ext/zip.png differ diff --git a/TextLocator/Service/NoTextFileService.cs b/TextLocator/Service/NoTextFileService.cs index fe71fdf185678a9d9f6c030b802efcb7bf4887a7..c4deb201a17403caab962d9a4f45df7329e1f5ca 100644 --- a/TextLocator/Service/NoTextFileService.cs +++ b/TextLocator/Service/NoTextFileService.cs @@ -1,6 +1,7 @@ using log4net; using System; using System.Text; +using TextLocator.Util; namespace TextLocator.Service { @@ -16,17 +17,13 @@ namespace TextLocator.Service try { System.IO.FileInfo fileInfo = new System.IO.FileInfo(filePath); - // 如果文件存在 - if (fileInfo != null && fileInfo.Exists) - { - System.Diagnostics.FileVersionInfo info = System.Diagnostics.FileVersionInfo.GetVersionInfo(filePath); - StringBuilder builder = new StringBuilder(); - builder.Append("文件名称:" + info.FileName.Substring(info.FileName.LastIndexOf("\\") + 1)); - builder.Append(";更新时间:" + fileInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss")); - builder.Append(";文件大小:" + Math.Ceiling(fileInfo.Length / 1024.0) + " KB"); + string fileName = filePath.Substring(filePath.LastIndexOf("\\") + 1); + StringBuilder builder = new StringBuilder(); + builder.Append("文件名称:" + fileName); + builder.Append(";更新时间:" + fileInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss")); + builder.Append(";文件大小:" + FileUtil.GetFileSizeFriendly(fileInfo.Length)); - return builder.ToString(); - } + return builder.ToString(); } catch (Exception ex) { diff --git a/TextLocator/Service/ZipFileService.cs b/TextLocator/Service/ZipFileService.cs new file mode 100644 index 0000000000000000000000000000000000000000..fda4e9d45dd46ec249db5508258d3fba3d5922e9 --- /dev/null +++ b/TextLocator/Service/ZipFileService.cs @@ -0,0 +1,60 @@ +using log4net; +using SharpCompress.Archives; +using SharpCompress.Common; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TextLocator.Core; +using TextLocator.Exceptions; +using TextLocator.Factory; +using TextLocator.Util; + +namespace TextLocator.Service +{ + /// + /// 压缩包文件服务 + /// + public class ZipFileService : IFileInfoService + { + private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private static object locker = new object(); + + public string GetFileContent(string filePath) + { + // 内容 + StringBuilder builder = new StringBuilder(); + lock (locker) + { + try + { + // 压缩包解压 + builder.Append("名称:" + filePath.Substring(filePath.LastIndexOf("\\") + 1)); + builder.Append(" 大小:" + FileUtil.GetFileSizeFriendly(new FileInfo(filePath).Length) + " =>\r\n"); + + builder.Append(" 列表:=>\r\n"); + using (FileStream file = new FileStream(filePath, FileMode.Open, FileAccess.Read)) + { + using (var archive = ArchiveFactory.Open(file)) { + foreach (var entry in archive.Entries) + { + if (!entry.IsDirectory) + { + builder.Append(String.Format("  {0}, {1}\r\n", entry.Key, FileUtil.GetFileSizeFriendly(entry.Size))); + } + } + } + } + } + catch (Exception ex) + { + log.Error(filePath + " -> " + ex.Message, ex); + } + } + return builder.ToString(); + } + } +} diff --git a/TextLocator/SettingWindow.xaml b/TextLocator/SettingWindow.xaml index 22cafdcd53297095455cf7cc5e90139cd2ad73a3..b2a4b640649e72435893325b6f79d5bc6c425fa7 100644 --- a/TextLocator/SettingWindow.xaml +++ b/TextLocator/SettingWindow.xaml @@ -4,6 +4,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:TextLocator" + xmlns:input="clr-namespace:System.Windows.Input;assembly=PresentationCore" mc:Ignorable="d" x:Name="hotkey" Title="设置" Height="380" Width="520" WindowStartupLocation="CenterScreen" WindowStyle="ToolWindow" ResizeMode="CanMinimize" Icon="/Resource/App.ico" Loaded="Window_Loaded" Closed="Window_Closed" > @@ -13,27 +14,44 @@ - + - - - + + - - + - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TextLocator/SettingWindow.xaml.cs b/TextLocator/SettingWindow.xaml.cs index 7d07b57f2da20018d5abf18512f7e2620149aaba..eb5ca680bf942b68bcceb78fc4351bca6ffc867d 100644 --- a/TextLocator/SettingWindow.xaml.cs +++ b/TextLocator/SettingWindow.xaml.cs @@ -5,9 +5,11 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; +using System.Text.RegularExpressions; using System.Windows; using System.Windows.Controls; using System.Windows.Media; +using TextLocator.Core; using TextLocator.HotKey; using TextLocator.Util; @@ -45,6 +47,24 @@ namespace TextLocator /// private void Window_Loaded(object sender, RoutedEventArgs e) { + // 加载配置 + LoadConfig(); + } + + /// + /// 加载配置信息 + /// + private void LoadConfig() + { + // 线程池 + this.MinThreads.Text = AppConst.THREAD_POOL_MIN_SIZE + ""; + this.MaxThreads.Text = AppConst.THREAD_POOL_MAX_SIZE + ""; + + // 每页显示条数 + this.ResultListPageSize.Text = AppConst.MRESULT_LIST_PAGE_SIZE + ""; + + // 文件读取超时时间 + this.FileReadTimeout.Text = AppConst.FILE_READ_TIMEOUT + ""; } #region 保存并关闭 @@ -53,8 +73,99 @@ namespace TextLocator /// /// /// - private void SaveClose_Click(object sender, RoutedEventArgs e) + private async void SaveClose_Click(object sender, RoutedEventArgs e) { + // 线程池 + string minThreadsText = this.MinThreads.Text; + string maxThreadsText = this.MaxThreads.Text; + + // 每页显示条数 + string ResultListPageSizeText = this.ResultListPageSize.Text; + + // 文件读取超时时间 + string fileReadTimeoutText = this.FileReadTimeout.Text; + + // 转换,验证 + int minThreads = 0; + try + { + minThreads = int.Parse(minThreadsText); + } + catch + { + Message.ShowWarning("MessageContainer", "最小线程数错误"); + return; + } + int maxThreads = 0; + try + { + maxThreads = int.Parse(maxThreadsText); + } + catch + { + Message.ShowWarning("MessageContainer", "最大线程数错误"); + return; + } + if (minThreads > maxThreads) + { + Message.ShowWarning("MessageContainer", "最小线程数大于最大线程数"); + return; + } + if (maxThreads > 128) + { + var result = await MessageBoxR.ConfirmInContainer("DialogContaioner", "线程数不是越大越好,你确定吗?", "提示"); + if (result == MessageBoxResult.Cancel) + { + return; + } + } + + int ResultListPageSize = 0; + try + { + ResultListPageSize = int.Parse(ResultListPageSizeText); + } + catch + { + Message.ShowWarning("MessageContainer", "分页条数错误"); + return; + } + if (ResultListPageSize < 50 || ResultListPageSize > 300) + { + Message.ShowWarning("MessageContainer", "建议设置在50 - 300范围内"); + return; + } + + int fileReadTimeout = 0; + try + { + fileReadTimeout = int.Parse(fileReadTimeoutText); + } + catch + { + Message.ShowWarning("MessageContainer", "文件读取超时时间错误"); + return; + } + if (fileReadTimeout < 5 * 60 || fileReadTimeout > 15 * 60) + { + Message.ShowWarning("MessageContainer", "建议设置在5 - 15分钟范围内"); + return; + } + + // 刷新、保存 + AppConst.THREAD_POOL_MIN_SIZE = minThreads; + AppConst.THREAD_POOL_MAX_SIZE = maxThreads; + AppCore.SetThreadPoolSize(); + + AppConst.MRESULT_LIST_PAGE_SIZE = ResultListPageSize; + AppUtil.WriteValue("AppConfig", "ResultListPageSize", AppConst.MRESULT_LIST_PAGE_SIZE + ""); + log.Debug("修改结果列表分页条数:" + AppConst.MRESULT_LIST_PAGE_SIZE); + + + AppConst.FILE_READ_TIMEOUT = fileReadTimeout; + AppUtil.WriteValue("AppConfig", "FileReadTimeout", AppConst.FILE_READ_TIMEOUT + ""); + log.Debug("修改文件读取超时时间:" + AppConst.FILE_READ_TIMEOUT); + this.Close(); } #endregion @@ -68,5 +179,15 @@ namespace TextLocator { _instance = null; } + + /// + /// 数字文本框预览输入 + /// + /// + /// + private void Number_TextBox_PreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e) + { + e.Handled = new Regex("[^0-9.-]+").IsMatch(e.Text); + } } } diff --git a/TextLocator/TextLocator.csproj b/TextLocator/TextLocator.csproj index a27cc9c3b743cfd578385465af6f7d36bc5a1ffc..a913e9bdef3c3eb45926b9194a058017df0989dd 100644 --- a/TextLocator/TextLocator.csproj +++ b/TextLocator/TextLocator.csproj @@ -8,12 +8,13 @@ WinExe TextLocator TextLocator - v4.6 + v4.6.1 512 {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 4 true true + AnyCPU @@ -90,6 +91,9 @@ ..\packages\Rubyer.1.0.16\lib\net46\Rubyer.dll + + ..\packages\SharpCompress.0.30.1\lib\net461\SharpCompress.dll + ..\packages\Spire.Office.7.2.0\lib\net40\Spire.Barcode.dll @@ -133,9 +137,25 @@ ..\packages\Spire.Office.7.2.0\lib\net40\Spire.XLS.dll + + ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + + ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll + + + + ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.5.0.0\lib\net45\System.Runtime.CompilerServices.Unsafe.dll + + + ..\packages\System.Text.Encoding.CodePages.5.0.0\lib\net461\System.Text.Encoding.CodePages.dll + @@ -157,6 +177,9 @@ MSBuild:Compile Designer + + + SettingWindow.xaml @@ -330,5 +353,8 @@ + + + \ No newline at end of file diff --git a/TextLocator/Util/FileUtil.cs b/TextLocator/Util/FileUtil.cs index 254236ed9629394dfa0e4abb67be8a116a636d62..735106e6e37545be1ee306de53db1da7b795c996 100644 --- a/TextLocator/Util/FileUtil.cs +++ b/TextLocator/Util/FileUtil.cs @@ -58,6 +58,9 @@ namespace TextLocator.Util case FileType.纯文本: bitmap = Properties.Resources.txt; break; + case FileType.压缩包: + bitmap = Properties.Resources.zip; + break; default: bitmap = Properties.Resources.rtf; break; @@ -121,9 +124,9 @@ namespace TextLocator.Util /// 获取指定根目录下的子目录及其文档 /// /// 文档列表 - /// 过滤列表 /// 根目录路径 - public static void GetAllFiles(List filePaths, Regex regexExclude, string rootPath) + /// 过滤列表 + public static void GetAllFiles(List filePaths, string rootPath, Regex regexExclude = null) { // 根目录 DirectoryInfo rootDir = new DirectoryInfo(rootPath); @@ -146,7 +149,7 @@ namespace TextLocator.Util continue; } // 递归调用 - GetAllFiles(filePaths, regexExclude, dirPath); + GetAllFiles(filePaths, dirPath, regexExclude); } } catch (UnauthorizedAccessException ex) { @@ -206,9 +209,13 @@ namespace TextLocator.Util } catch (Exception ex) { - log.Error("索引清理失败:" + ex.Message, ex); + log.Error("文件删除失败:" + ex.Message, ex); } } + try + { + File.Delete(srcDir); + } catch { } } /// diff --git a/TextLocator/packages.config b/TextLocator/packages.config index d37b09135a0055f8642b92a656bf038e4a5c5eae..2275744224358de32e13b5d022dad596422f2988 100644 --- a/TextLocator/packages.config +++ b/TextLocator/packages.config @@ -11,6 +11,12 @@ + + + + + + \ No newline at end of file diff --git a/images/Cover.png b/images/Cover.png new file mode 100644 index 0000000000000000000000000000000000000000..0f48ce5a081ca84f71eeba4fed66e8fd8c20e7bf Binary files /dev/null and b/images/Cover.png differ diff --git a/images/Setting.png b/images/Setting.png new file mode 100644 index 0000000000000000000000000000000000000000..32780e14641daf3f7283aad66721f04b2046587d Binary files /dev/null and b/images/Setting.png differ