Skip to content

Commit

Permalink
Merge pull request #104 from dotnet-campus/t/lindexi/UsingHardLinkToZ…
Browse files Browse the repository at this point in the history
…ipNtfsDiskSize

添加使用硬连接减少磁盘空间占用工具
  • Loading branch information
kkwpsv authored Jan 5, 2024
2 parents de9be19 + fcb3199 commit 4e08d81
Show file tree
Hide file tree
Showing 19 changed files with 884 additions and 0 deletions.
9 changes: 9 additions & 0 deletions CopyAfterCompileTool/UsingHardLinkToZipNtfsDiskSize/App.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Application x:Class="UsingHardLinkToZipNtfsDiskSize.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:UsingHardLinkToZipNtfsDiskSize"
StartupUri="MainWindow.xaml">
<Application.Resources>

</Application.Resources>
</Application>
12 changes: 12 additions & 0 deletions CopyAfterCompileTool/UsingHardLinkToZipNtfsDiskSize/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.Configuration;
using System.Data;
using System.Windows;

namespace UsingHardLinkToZipNtfsDiskSize;
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System.Windows;

[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using System.Threading.Channels;
using Microsoft.Extensions.Logging;

namespace UsingHardLinkToZipNtfsDiskSize;

public class ChannelLoggerProvider : ILoggerProvider
{
public ChannelLoggerProvider(params IStringLoggerWriter[] stringLoggerWriterList)
{
_stringLoggerWriterList = stringLoggerWriterList;
var channel = Channel.CreateUnbounded<string>(new UnboundedChannelOptions()
{
SingleReader = true
});
_channel = channel;

Task.Run(WriteLogAsync);
}

private readonly IStringLoggerWriter[] _stringLoggerWriterList;

private async Task? WriteLogAsync()
{
while (!_channel.Reader.Completion.IsCompleted)
{
try
{
var message = await _channel.Reader.ReadAsync();
foreach (var stringLoggerWriter in _stringLoggerWriterList)
{
await stringLoggerWriter.WriteAsync(message);
}
}
catch (ChannelClosedException)
{
// 结束
}
}

foreach (var stringLoggerWriter in _stringLoggerWriterList)
{
await stringLoggerWriter.DisposeAsync();
}
}

private readonly Channel<string> _channel;
public void Dispose()
{
ChannelWriter<string> channelWriter = _channel.Writer;
channelWriter.TryComplete();
}

public ILogger CreateLogger(string categoryName)
{
return new ChannelLogger(_channel.Writer);
}

class ChannelLogger : ILogger, IDisposable
{
public ChannelLogger(ChannelWriter<string> writer)
{
_writer = writer;
}

private readonly ChannelWriter<string> _writer;

public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
{
var message = $"{DateTime.Now:yyyy.MM.dd HH:mm:ss,fff} [{logLevel}][{eventId}] {formatter(state, exception)}";
_ = _writer.WriteAsync(message);
}

public bool IsEnabled(LogLevel logLevel)
{
return true;
}

public IDisposable? BeginScope<TState>(TState state) where TState : notnull
{
return this;
}

public void Dispose()
{
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Windows.Controls;

namespace UsingHardLinkToZipNtfsDiskSize;

class DispatcherStringLoggerWriter : IStringLoggerWriter
{
public DispatcherStringLoggerWriter(TextBlock logTextBlock)
{
_logTextBlock = logTextBlock;
}

private readonly TextBlock _logTextBlock;

private string _lastMessage = string.Empty;
private bool _isInvalidate = false;

public ValueTask WriteAsync(string message)
{
_lastMessage = message;

if (!_isInvalidate)
{
_isInvalidate = true;

_logTextBlock.Dispatcher.InvokeAsync(() =>
{
_logTextBlock.Text = _lastMessage;
_isInvalidate = false;
});
}

return ValueTask.CompletedTask;
}

public ValueTask DisposeAsync()
{
return ValueTask.CompletedTask;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.ComponentModel.DataAnnotations;

namespace UsingHardLinkToZipNtfsDiskSize;

public class FileRecordModel
{
[Key]
[Required]
public string FilePath { set; get; } = null!;

[Required]
public long FileLength { set; get; }

[Required]
public string FileSha1Hash { set; get; } = null!;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Microsoft.EntityFrameworkCore;

namespace UsingHardLinkToZipNtfsDiskSize;

public class FileStorageContext : DbContext
{
public FileStorageContext()
{
// 用于设计时
_sqliteFile = "FileManger.db";
}

public FileStorageContext(string sqliteFile)
{
_sqliteFile = sqliteFile;
}

private readonly string _sqliteFile;

public DbSet<FileStorageModel> FileStorageModel { set; get; } = null!;
public DbSet<FileRecordModel> FileRecordModel { set; get; } = null!;

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlite($"Filename={_sqliteFile}");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System.ComponentModel.DataAnnotations;

namespace UsingHardLinkToZipNtfsDiskSize;

public class FileStorageModel
{
[Key]
[Required]
public string FileSha1Hash { set; get; } = null!;

/// <summary>
/// 原始的文件路径
/// </summary>
[Required]
public string OriginFilePath { set; get; } = null!;

/// <summary>
/// 有多少个文件引用了
/// </summary>
public long ReferenceCount { set; get; }

/// <summary>
/// 文件大小
/// </summary>
public long FileLength { set; get; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace UsingHardLinkToZipNtfsDiskSize;

public interface IStringLoggerWriter : IAsyncDisposable
{
ValueTask WriteAsync(string message);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.IO;
using System.Text;

namespace UsingHardLinkToZipNtfsDiskSize;

public class LogFileStringLoggerWriter : IStringLoggerWriter
{
public LogFileStringLoggerWriter(DirectoryInfo logFolder)
{
_logFolder = logFolder;
var logFile = Path.Join(logFolder.FullName, "Log.txt");
var fileStream = new FileStream(logFile, FileMode.Append, FileAccess.Write, FileShare.Read);
_fileStream = fileStream;
var streamWriter = new StreamWriter(fileStream, Encoding.UTF8);
_streamWriter = streamWriter;
}

private readonly DirectoryInfo _logFolder;
private readonly FileStream _fileStream;
private readonly StreamWriter _streamWriter;

public async ValueTask WriteAsync(string message)
{
await _streamWriter.WriteLineAsync(message);
}

public async ValueTask DisposeAsync()
{
await _streamWriter.DisposeAsync();
await _fileStream.DisposeAsync();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<Window x:Class="UsingHardLinkToZipNtfsDiskSize.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:UsingHardLinkToZipNtfsDiskSize"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid Background="Transparent" AllowDrop="true" DragEnter="Grid_OnDragEnter">
<Rectangle Margin="10,10,10,10"
StrokeDashArray="2 2" StrokeThickness="2" Stroke="Gray" RadiusX="5" RadiusY="5"></Rectangle>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="50">Drag Folder Here</TextBlock>
</Grid>
<TextBlock x:Name="LogTextBlock" Grid.Row="1" Margin="2 2 2 2" TextWrapping="NoWrap"></TextBlock>
</Grid>
</Window>
Loading

0 comments on commit 4e08d81

Please sign in to comment.