MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Threading;
using System.IO;
namespace JsonAnalysis
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
#region Window_Loaded
public MainWindow( )
{
InitializeComponent( );
//#region 设置程序全屏
//this.Top = 0;
//this.Left = 0;
//this.WindowStartupLocation = WindowStartupLocation.Manual;
//this.MinWidth = 640;
//this.MinHeight = 480;
this.Width = SystemParameters.PrimaryScreenWidth;
this.Height = SystemParameters.PrimaryScreenHeight;
//this.Width = SystemParameters.WorkArea.Width;
//this.Height = SystemParameters.WorkArea.Height;
//#endregion
}
private void window_Loaded( object sender, RoutedEventArgs e )
{
this.Title = "Json 文件分析工具 V2022.05.07 2200";
this.tb_JsonFilePath.Text = @".\json";
#region 启动状态栏区计时器
dispatcherTimer = new System.Windows.Threading.DispatcherTimer( );
dispatcherTimer.Tick += new EventHandler( OnTimedEvent );
dispatcherTimer.Interval = new TimeSpan( 0, 0, 1 );
dispatcherTimer.Start( );
#endregion
}
private void window_Closing( object sender, System.ComponentModel.CancelEventArgs e )
{
//if ( MessageBox.Show( "确认退出程序 ?", "", MessageBoxButton.OKCancel, MessageBoxImage.Question ) == MessageBoxResult.Cancel ) e.Cancel = true;
}
#endregion Window_Loaded
#region 状态栏区计时器事件函数
/// <summary>
/// 状态栏时间显示区计时器.
/// </summary>
private System.Windows.Threading.DispatcherTimer dispatcherTimer = null;
/// <summary>
/// 计时器函数 OnTimedEvent 中用于重置日志类文件.
/// 以便每天生成一个独立的日志文件.
/// </summary>
DateTime AppLoadTime = DateTime.Now;
/// <summary>
/// 状态栏区计时器事件函数
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnTimedEvent( object sender, EventArgs e )
{
tssl_Time.Text = DateTime.Now.ToString( "yyyy-MM-dd HH:mm:ss dddd" );
TimeSpan ts = DateTime.Now - AppLoadTime;
this.tssl_AppRunTime.Text = "程序已运行 " +
ts.Days.ToString( ) + " 天 " + ts.Hours.ToString( "00" ) + " 小时 " +
ts.Minutes.ToString( "00" ) + " 分钟 " + ts.Seconds.ToString( "00" ) + " 秒 ";
}
#endregion
#region 控件事件
//日志文件框自动下滚
private void tb_Log_TextChanged( object sender, TextChangedEventArgs e )
{
if ( !( sender is TextBox ) ) return;
TextBox tbx = (TextBox)sender;
tbx.ScrollToEnd( );
}
/// <summary>
/// 启动分析按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_JsonAnalysis_Click( object sender, RoutedEventArgs e )
{
string target_json_file_path = this.tb_JsonFilePath.Text;
StartWorkingThread( target_json_file_path );
}
/// <summary>
/// 路径选择按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_JsonFilePath_Click( object sender, RoutedEventArgs e )
{
System.Windows.Forms.FolderBrowserDialog folderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog( );
if ( folderBrowserDialog.ShowDialog( ) == System.Windows.Forms.DialogResult.OK )
{
this.tb_JsonFilePath.Text = folderBrowserDialog.SelectedPath;
}
}
#endregion 控件事件
#region 日志与文件写入
private string ResultTxtFilePath = @".\";
private void WriteResultTxtFile( string result_file_name, string data )
{
File.AppendAllText( result_file_name, data );
}
private void ShowLog( string log )
{
Dispatcher.Invoke( new Action( delegate ( )
{
tb_Log.Text += DateTime.Now.ToString( "yyyy-MM-dd HH:mm:ss" ) + " " + log + Environment.NewLine;
} ), null );
}
#endregion 日志与文件写入
#region 分析工作线程
/// <summary>
/// 结果集
/// </summary>
private List<JsonAnalysisResult> m_JsonAnalysisResultList = new List<JsonAnalysisResult>( );
/// <summary>
/// 启动工作线程.
/// </summary>
private void StartWorkingThread( string target_json_file_path )
{
this.cbx_Settings.IsEnabled = false;
m_JsonAnalysisResultList.Clear( );
Thread thread = new Thread( ( ) =>
{
try
{
Thread.CurrentThread.IsBackground = true;
if ( !Directory.Exists( target_json_file_path ) )
{
ShowLog( "路径不存在." );
Dispatcher.Invoke( new Action( delegate ( ) { this.cbx_Settings.IsEnabled = true; } ), null );
return;
}
ShowLog( "获取 json 文件中..." );
string[ ] json_files = Directory.GetFiles( target_json_file_path, "*.json" );
ShowLog( "发现 json 文件 " + json_files.Length + " 个." );
ShowLog( "开始文件分析中... " );
if ( !target_json_file_path.EndsWith( "\\" ) ) target_json_file_path += "\\";
ResultTxtFilePath = target_json_file_path + "result.txt";
//文件存在时是否删除旧文件.要保留原文件则注释掉下面的代码.
if ( File.Exists( ResultTxtFilePath ) )
{
if ( MessageBox.Show( "已存在结果文件, 是否覆盖?\n<是>覆盖并继续.\n<否>取消并中止操作.", "", MessageBoxButton.YesNo ) == MessageBoxResult.No )
{
Dispatcher.Invoke( new Action( delegate ( ) { this.cbx_Settings.IsEnabled = true; } ), null );
return;
}
File.Delete( ResultTxtFilePath );
}
//按文件名排序, 然后遍历每个文件
foreach ( string file in json_files.OrderBy( n => n ) )
{
if ( !File.Exists( file ) ) { ShowLog( "分析文件时出错, 文件不存在. -> " + file ); return; }
string json_data = File.ReadAllText( file );
JsonFileAnalysis( file, json_data );
}
ShowLog( "json 文件分析完成, 输出结果到文件=>" + ResultTxtFilePath );
foreach ( var data in m_JsonAnalysisResultList )
{
WriteResultTxtFile( ResultTxtFilePath, data.JsonFile + " " + data.ResultData + Environment.NewLine );
}
ShowLog( "执行完成, 结果已经输出到文件=>" + ResultTxtFilePath );
Dispatcher.Invoke( new Action( delegate ( ) { this.cbx_Settings.IsEnabled = true; } ), null );
return;
}
catch ( Exception ex )
{
Dispatcher.Invoke( new Action( delegate ( ) { this.cbx_Settings.IsEnabled = true; } ), null );
ShowLog( "程序工作线程中发生异常 -> " + ex.Message );
}
} );
thread.Start( );
}
/// <summary>
/// 用于分隔不同路径的字符
/// </summary>
private const string path_char = ".";
/// <summary>
/// 解析json数据
/// </summary>
/// <param name="json_file_name">json文件名</param>
/// <param name="json_data">json实际数组字符串</param>
private void JsonFileAnalysis( string json_file_name, string json_data )
{
JObject json_obj = (JObject)JsonConvert.DeserializeObject( json_data );
JsonFileAnalysis( json_file_name, json_obj, string.Empty );
}
/// <summary>
/// 文件分析主函数.
/// 注意些函数递归调用, 分析json中的层级结构
/// </summary>
/// <param name="json_file_name">json文件名</param>
/// <param name="json_obj">json对象. 用于递归调用.</param>
/// <param name="path_key">累计的path路径信息</param>
private void JsonFileAnalysis( string json_file_name, JToken json_obj, string path_key )
{
string current_key;
//string current_value ;
string current_data = string.Empty;
List<string> array_data = new List<string>( );
if ( json_obj.Type == JTokenType.Object )
foreach ( var obj in json_obj as JObject )
{
current_key = obj.Key;
switch ( obj.Value.Type )
{
case JTokenType.Property:
{
break;
}
case JTokenType.Object:
{
if ( string.IsNullOrWhiteSpace( path_key ) )
JsonFileAnalysis( json_file_name, obj.Value, current_key );
else
JsonFileAnalysis( json_file_name, obj.Value, path_key + path_char + obj.Key );
break;
}
case JTokenType.Null:
{
current_data = current_key + "=Null";
break;
}
case JTokenType.Undefined:
{
current_data = current_key + "=Undefined";
break;
}
case JTokenType.Date:
{
current_data = current_key + "=" + obj.Value.ToString( );
break;
}
case JTokenType.Array:
{
JArray jArray = (JArray)JsonConvert.DeserializeObject( obj.Value.ToString( ) );
for ( int i = 0; i < jArray.Count; i++ )
{
if ( jArray[ i ].Type == JTokenType.Object )
{
if ( string.IsNullOrWhiteSpace( path_key ) )
JsonFileAnalysis( json_file_name, jArray[ i ].Value<JToken>( ), current_key + "[" + i.ToString( ) + "]" );
else
JsonFileAnalysis( json_file_name, jArray[ i ].Value<JToken>( ), path_key + path_char +current_key + "[" + i.ToString( ) + "]");
}
else
array_data.Add( current_key + "[" + i.ToString( ) + "]=" + jArray[ i ].ToString( ) );
}
break;
}
case JTokenType.Boolean:
{
current_data = current_key + "=" + obj.Value.ToString( );
break;
}
case JTokenType.Integer:
{
current_data = current_key + "=" + obj.Value.ToString( );
break;
}
case JTokenType.Float:
{
current_data = current_key + "=" + obj.Value.ToString( );
break;
}
case JTokenType.String:
{
current_data = current_key + "=" + obj.Value.ToString( );
break;
}
default:
{
break;
}
}
//如果存在键值. 则添加值数据且将前面的路径path挂载到头部.
if ( !string.IsNullOrWhiteSpace( current_data ) )
{
//string result = string.Empty;
//if ( string.IsNullOrWhiteSpace( path_key ) )
// result = json_file_name + " " + current_data;
//else
// result = json_file_name + " " + path_key + path_char + current_data;
string result = string.Empty;
if ( string.IsNullOrWhiteSpace( path_key ) )
result = current_data;
else
result = path_key + path_char + current_data;
if ( m_JsonAnalysisResultList.FindAll( n => n.ResultData == result ).Count <= 0 )
{
m_JsonAnalysisResultList.Add( new JsonAnalysisResult( ) { JsonFile = json_file_name, ResultData = result } );
//WriteResultTxtFile( ResultTxtFilePath, result + Environment.NewLine );
ShowLog( result );
}
else
{
//ShowLog( "发现重复键值=>" + json_file_name + " " + result );
}
}
//如果存在数组. 则添加数组数据
foreach ( var arr_data in array_data )
{
//string result = string.Empty;
//if ( string.IsNullOrWhiteSpace( path_key ) )
// result = json_file_name + " " + arr_data;
//else
// result = json_file_name + " " + path_key + path_char + arr_data;
//m_JsonAnalysisResultList.Add( new JsonAnalysisResult( ) { JsonFile = ResultTxtFilePath, ResultData = result } );
WriteResultTxtFile( ResultTxtFilePath, result + Environment.NewLine );
//ShowLog( result );
string result = string.Empty;
if ( string.IsNullOrWhiteSpace( path_key ) )
result = arr_data;
else
result = path_key + path_char + arr_data;
if ( m_JsonAnalysisResultList.FindAll( n => n.ResultData == result ).Count <= 0 )
{
m_JsonAnalysisResultList.Add( new JsonAnalysisResult( ) { JsonFile = json_file_name, ResultData = result } );
//WriteResultTxtFile( ResultTxtFilePath, result + Environment.NewLine );
ShowLog( result );
}
else
{
//ShowLog( "发现重复键值=>" + json_file_name + " " + result );
}
}
}
}
#endregion 分析工作线程
}
}
JsonAnalysisResult.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace JsonAnalysis
{
/// <summary>
/// 用于保存分析结果
/// </summary>
public class JsonAnalysisResult
{
/// <summary>
/// json 文件名字
/// </summary>
public string JsonFile { get; set; }
/// <summary>
/// 分析结果数据
/// </summary>
public string ResultData { get; set; }
}
}
|