ASP.NET Web API 应用教程(一) ——数据流使用

 

相信已经有很多文章来介绍ASP.Net Web API 技术,本系列文章主要介绍如何使用数据流,HTTPS,以及可扩展的Web API 方面的技术,系列文章主要有三篇内容。

主要内容如下:

I  数据流

II 使用HTTPS

III 可扩展的Web API 文档

项目环境要求

  • VS 2012(SP4)及以上,
  • .Net 框架4.5.1
  • Nuget包,可在packages.config 文件中查寻

本文涉及的知识点

  1. ActionFilter
  2. AuthorizationFilter
  3. DelegateHandler
  4. Different Web API routing 属性
  5. MediaTypeFormatter
  6. OWIN
  7. Self Hosting
  8. Web API 文档及可扩展功能

.Net 框架

  1. Async/Await
  2. .NET reflection
  3. Serialization
  4. ASP.NET Web API/MVC Error handling
  5. IIS ,HTTPS 及Certificate
  6. 设计准则及技术

前言

自从ASP.NET MVC 4之后.Net 框架开始支持ASP.NET Web API ,ASP.NET Web API 基于HTTP 协议建立的,是构建 RESTful 服务和处理数据的理想平台,旨在使用HTTP 技术实现对多平台的支持。

ASP.NET Web API 以request-response 的消息转换模式为主,客户端向服务器发送请求,服务器端响应客户端请求。响应可同步或异步。

个人认为使用Web API创建应用需要注意的三个关键点:

  • 采用服务及方法满足的目标
  • 每个方法的输入,如请求
  • 每个方法的输出,如响应

通常情况下,Asp.Net Web API 定义method语法与HTTP方法一一对应的,如自定义方法名 GetPysicians(),则与HTTP中Get 方法匹配。下图是常用匹配表。

但是此方法在很多情况下,并不实用,假如你想在单个API controller 类中定义多个Get 或Post 方法,在这种情况下,需要定义包含action 的路径,将Action 作为URI 的一部分。以下是配置代码:

  1. 1: public static void Register(HttpConfiguration config)
  1. 2: {
  1. 3: // Web API configuration and services
  1. 4: // Web API routes
  1. 5: config.MapHttpAttributeRoutes();
  1. 6:
  1. 7: config.Routes.MapHttpRoute(name: "PhysicianApi",
  1. 8: routeTemplate: "{controller}/{action}/{id}",
  1. 9: defaults: new { id = RouteParameter.Optional });
  1. 10: }

但是此方法不足以应对所有情况,如果想实现从中央仓库删除文件,并且想调用同一个方法来获取文件,这种情况下,Web API 框架需要伪装Get 及Delete对应的HTTP 方法属性。如图所示:

RemoveFile 方法可被Delete(HttpDelete) 或 Get(HttpGet)方法同时调用,从某种程度来说,HTTP 方法使开发人员命名 API“方法”变得简单而标准。

Web API框架也提供了一些其他功能来处理路径方面的问题,与MVC 的路径处理方法相似。因此可定义不同类型的Action方法。

数据流

网络App 最常见的执行操作就是获取数据流。ASP.NET Web API 能够处理客户端与服务器端传输的重量级的数据流,数据流可来源于目录文件,也可是数据库中的二进制文件。本文主要介绍两种方法“Download”和“Upload”实现数据流相关的功能,Download是从服务器下载数据操作,而Upload则是上传数据到服务器。

相关项目

  • WebAPIDataStreaming
  • WebAPIClient
  • POCOLibrary

在对代码解释之前,首先来了解如何配置IIS(7.5)和Web API 服务Web.Config 文件。

1. 保证Downloads/Uploads 涉及的文件具有读写权限。

2. 保证有足够容量的内容或因公安空间处理大文件。

3. 如果文件较大

a. 配置Web.Config 文件时,保证 maxRequestLength 时响应时间 executionTimeout 合理。具体的值主要依赖于数据大小,允许一次性上传的最大数据为2 GB

b. 保证 maxAllowedContentLength 在requestFiltering部分配置下正确设置,默认值为30MB,最大值4GB

一旦完成预先配置,那么创建数据流服务就非常简单了,首先 需要定义文件流“ApiController”,如下:

  1. 1: /// <summary>
  1. 2: /// File streaming API
  1. 3: /// </summary>
  1. 4: [RoutePrefix("filestreaming")]
  1. 5: [RequestModelValidator]
  1. 6: public class StreamFilesController : ApiController
  1. 7: {
  1. 8: /// <summary>
  1. 9: /// Get File meta data
  1. 10: /// </summary>
  1. 11: /// <param name="fileName">FileName value</param>
  1. 12: /// <returns>FileMeta data response.</returns>
  1. 13: [Route("getfilemetadata")]
  1. 14: public HttpResponseMessage GetFileMetaData(string fileName)
  1. 15: {
  1. 16: // .........................................
  1. 17: // Full code available in the source control
  1. 18: // .........................................
  1. 19:  
  1. 20: }
  1. 21:  
  1. 22: /// <summary>
  1. 23: /// Search file and return its meta data in all download directories
  1. 24: /// </summary>
  1. 25: /// <param name="fileName">FileName value</param>
  1. 26: /// <returns>List of file meta datas response</returns>
  1. 27: [HttpGet]
  1. 28: [Route("searchfileindownloaddirectory")]
  1. 29: public HttpResponseMessage SearchFileInDownloadDirectory(string fileName)
  1. 30: {
  1. 31: // .........................................
  1. 32: // Full code available in the source control
  1. 33: // .........................................
  1. 34: }
  1. 35:  
  1. 36: /// <summary>
  1. 37: /// Asynchronous Download file
  1. 38: /// </summary>
  1. 39: /// <param name="fileName">FileName value</param>
  1. 40: /// <returns>Tasked File stream response</returns>
  1. 41: [Route("downloadasync")]
  1. 42: [HttpGet]
  1. 43: public async Task<HttpResponseMessage> DownloadFileAsync(string fileName)
  1. 44: {
  1. 45: // .........................................
  1. 46: // Full code available in the source control
  1. 47: // .........................................
  1. 48: }
  1. 49:  
  1. 50: /// <summary>
  1. 51: /// Download file
  1. 52: /// </summary>
  1. 53: /// <param name="fileName">FileName value</param>
  1. 54: /// <returns>File stream response</returns>
  1. 55: [Route("download")]
  1. 56: [HttpGet]
  1. 57: public HttpResponseMessage DownloadFile(string fileName)
  1. 58: {
  1. 59: // .........................................
  1. 60: // Full code available in the source control
  1. 61: // .........................................
  1. 62: }
  1. 63:  
  1. 64: /// <summary>
  1. 65: /// Upload file(s)
  1. 66: /// </summary>
  1. 67: /// <param name="overWrite">An indicator to overwrite a file if it exist in the server</param>
  1. 68: /// <returns>Message response</returns>
  1. 69: [Route("upload")]
  1. 70: [HttpPost]
  1. 71: public HttpResponseMessage UploadFile(bool overWrite)
  1. 72: {
  1. 73: // .........................................
  1. 74: // Full code available in the source control
  1. 75: // .........................................
  1. 76: }
  1. 77:  
  1. 78: /// <summary>
  1. 79: /// Asynchronous Upload file
  1. 80: /// </summary>
  1. 81: /// <param name="overWrite">An indicator to overwrite a file if it exist in the server</param>
  1. 82: /// <returns>Tasked Message response</returns>
  1. 83: [Route("uploadasync")]
  1. 84: [HttpPost]
  1. 85: public async Task<HttpResponseMessage> UploadFileAsync(bool overWrite)
  1. 86: {
  1. 87: // .........................................
  1. 88: // Full code available in the source control
  1. 89: // .........................................
  1. 90: }
  1. 91: }

Download 服务方法首先需要确认请求的文件是否存在,如果未找到,则返回错误提示“file is not found”,如果找到此文件,内容则转换为字节附加到响应对象,为“application/octet-stream” MIMI 内容类型。

  1. 1: /// <summary>
  1. 2: /// Download file
  1. 3: /// </summary>
  1. 4: /// <param name="fileName">FileName value<param>
  1. 5: /// <returns>File stream response<returns>
  1. 6: [Route("download")]
  1. 7: [HttpGet]
  1. 8: public HttpResponseMessage DownloadFile(string fileName)
  1. 9: {
  1. 10: HttpResponseMessage response = Request.CreateResponse();
  1. 11: FileMetaData metaData = new FileMetaData();
  1. 12: try
  1. 13: {
  1. 14: string filePath = Path.Combine(this.GetDownloadPath(), @"\", fileName);
  1. 15: FileInfo fileInfo = new FileInfo(filePath);
  1. 16:  
  1. 17: if (!fileInfo.Exists)
  1. 18: {
  1. 19: metaData.FileResponseMessage.IsExists = false;
  1. 20: metaData.FileResponseMessage.Content = string.Format("{0} file is not found !", fileName);
  1. 21: response = Request.CreateResponse(HttpStatusCode.NotFound, metaData, new MediaTypeHeaderValue("text/json"));
  1. 22: }
  1. 23: else
  1. 24: {
  1. 25: response.Headers.AcceptRanges.Add("bytes");
  1. 26: response.StatusCode = HttpStatusCode.OK;
  1. 27: response.Content = new StreamContent(fileInfo.ReadStream());
  1. 28: response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
  1. 29: response.Content.Headers.ContentDisposition.FileName = fileName;
  1. 30: response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
  1. 31: response.Content.Headers.ContentLength = fileInfo.Length;
  1. 32: }
  1. 33: }
  1. 34: catch (Exception exception)
  1. 35: {
  1. 36: // Log exception and return gracefully
  1. 37: metaData = new FileMetaData();
  1. 38: metaData.FileResponseMessage.Content = ProcessException(exception);
  1. 39: response = Request.CreateResponse(HttpStatusCode.InternalServerError, metaData, new MediaTypeHeaderValue("text/json"));
  1. 40: }
  1. 41: return response;
  1. 42: }

Upload服务方法则会在multipart/form-data MIMI 内容类型执行,首先会检测HTTP 请求的内容类型是否是多主体,如果是,则对比内容长度是否超过最大尺寸,如果没有超过,则开始上传内容,当操作完成之后,则提示相应的信息。

代码片段如下:

  1. 1: /// <summary>
  1. 2: /// Upload file(s)
  1. 3: /// </summary>
  1. 4: /// <param name="overWrite">An indicator to overwrite a file if it exist in the server.</param>
  1. 5: /// <returns>Message response</returns>
  1. 6: [Route("upload")]
  1. 7: [HttpPost]
  1. 8: public HttpResponseMessage UploadFile(bool overWrite)
  1. 9: {
  1. 10: HttpResponseMessage response = Request.CreateResponse();
  1. 11: List<FileResponseMessage> fileResponseMessages = new List<FileResponseMessage>();
  1. 12: FileResponseMessage fileResponseMessage = new FileResponseMessage { IsExists = false };
  1. 13:  
  1. 14: try
  1. 15: {
  1. 16: if (!Request.Content.IsMimeMultipartContent())
  1. 17: {
  1. 18: fileResponseMessage.Content = "Upload data request is not valid !";
  1. 19: fileResponseMessages.Add(fileResponseMessage);
  1. 20: response = Request.CreateResponse(HttpStatusCode.UnsupportedMediaType, fileResponseMessages, new MediaTypeHeaderValue("text/json"));
  1. 21: }
  1. 22:  
  1. 23: else
  1. 24: {
  1. 25: response = ProcessUploadRequest(overWrite);
  1. 26: }
  1. 27: }
  1. 28: catch (Exception exception)
  1. 29: {
  1. 30: // Log exception and return gracefully
  1. 31: fileResponseMessage = new FileResponseMessage { IsExists = false };
  1. 32: fileResponseMessage.Content = ProcessException(exception);
  1. 33: fileResponseMessages.Add(fileResponseMessage);
  1. 34: response = Request.CreateResponse(HttpStatusCode.InternalServerError, fileResponseMessages, new MediaTypeHeaderValue("text/json"));
  1. 35:  
  1. 36: }
  1. 37: return response;
  1. 38: }
  1. 39:  
  1. 40: /// <summary>
  1. 41: /// Asynchronous Upload file
  1. 42: /// </summary>
  1. 43: /// <param name="overWrite">An indicator to overwrite a file if it exist in the server.<param>
  1. 44: /// <returns>Tasked Message response</returns>
  1. 45: [Route("uploadasync")]
  1. 46: [HttpPost]
  1. 47: public async Task<HttpResponseMessage> UploadFileAsync(bool overWrite)
  1. 48: {
  1. 49: return await new TaskFactory().StartNew(
  1. 50: () =>
  1. 51: {
  1. 52: return UploadFile(overWrite);
  1. 53: });
  1. 54: }
  1. 55:  
  1. 56: /// <summary>
  1. 57: /// Process upload request in the server
  1. 58: /// </summary>
  1. 59: /// <param name="overWrite">An indicator to overwrite a file if it exist in the server.</param>
  1. 60: /// </returns>List of message object</returns>
  1. 61: private HttpResponseMessage ProcessUploadRequest(bool overWrite)
  1. 62: {
  1. 63: // .........................................
  1. 64: // Full code available in the source control
  1. 65: // .........................................
  1. 66: }

调用download 及 upload 文件方法是控制台应用,App 假定文件流服务通过HttpClient和相关类。基本下载文件代码,创建下载HTTP 请求对象。

  1. 1: /// <summary>
  1. 2: /// Download file
  1. 3: /// </summary>
  1. 4: /// <returns>Awaitable Task object</returns>
  1. 5: private static async Task DownloadFile()
  1. 6: {
  1. 7: Console.ForegroundColor = ConsoleColor.Green;
  1. 8: Console.WriteLine("Please specify file name with extension and Press Enter :- ");
  1. 9: string fileName = Console.ReadLine();
  1. 10: string localDownloadPath = string.Concat(@"c:\", fileName); // the path can be configurable
  1. 11: bool overWrite = true;
  1. 12: string actionURL = string.Concat("downloadasync?fileName=", fileName);
  1. 13:  
  1. 14: try
  1. 15: {
  1. 16: Console.WriteLine(string.Format("Start downloading @ {0}, {1} time ",
  1. 17: DateTime.Now.ToLongDateString(),
  1. 18: DateTime.Now.ToLongTimeString()));
  1. 19:  
  1. 20:  
  1. 21: using (HttpClient httpClient = new HttpClient())
  1. 22: {
  1. 23: httpClient.BaseAddress = baseStreamingURL;
  1. 24: HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, actionURL);
  1. 25:  
  1. 26: await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).
  1. 27: ContinueWith((response)
  1. 28: =>
  1. 29: {
  1. 30: Console.WriteLine();
  1. 31: try
  1. 32: {
  1. 33: ProcessDownloadResponse(localDownloadPath, overWrite, response);
  1. 34: }
  1. 35: catch (AggregateException aggregateException)
  1. 36: {
  1. 37: Console.ForegroundColor = ConsoleColor.Red;
  1. 38: Console.WriteLine(string.Format("Exception : ", aggregateException));
  1. 39: }
  1. 40: });
  1. 41: }
  1. 42: }
  1. 43: catch (Exception ex)
  1. 44: {
  1. 45: Console.ForegroundColor = ConsoleColor.Red;
  1. 46: Console.WriteLine(ex.Message);
  1. 47: }
  1. 48: }
  1. 49:  
  1. 50:  
  1. 51: /// <summary>
  1. 52: /// Process download response object
  1. 53: /// </summary>
  1. 54: /// <param name="localDownloadFilePath">Local download file path</param>
  1. 55: /// <param name="overWrite">An indicator to overwrite a file if it exist in the client.</param>
  1. 56: /// <param name="response">Awaitable HttpResponseMessage task value</param>
  1. 57: private static void ProcessDownloadResponse(string localDownloadFilePath, bool overWrite,
  1. 58: Task<HttpResponseMessage> response)
  1. 59: {
  1. 60: if (response.Result.IsSuccessStatusCode)
  1. 61: {
  1. 62: response.Result.Content.DownloadFile(localDownloadFilePath, overWrite).
  1. 63: ContinueWith((downloadmessage)
  1. 64: =>
  1. 65: {
  1. 66: Console.ForegroundColor = ConsoleColor.Green;
  1. 67: Console.WriteLine(downloadmessage.TryResult());
  1. 68: });
  1. 69: }
  1. 70: else
  1. 71: {
  1. 72: ProcessFailResponse(response);
  1. 73: }
  1. 74: }

注意上述代码中HttpClient 对象发送请求,并等待响应发送Header内容(HttpCompletionOption.ResponseHeadersRead )。而不是发送全部的响应内容文件。一旦Response header 被读,则执行验证,一旦验证成功,则执行下载方法。

以下代码调用upload 文件流,与下载方法类似,创建多主体表单数据,并发送给服务器端。

  1. 1: /// <summary>
  1. 2: /// Upload file
  1. 3: /// </summary>
  1. 4: /// <returns>Awaitable task object</returns>
  1. 5: private static async Task UploadFile()
  1. 6: {
  1. 7: try
  1. 8: {
  1. 9: string uploadRequestURI = "uploadasync?overWrite=true";
  1. 10:  
  1. 11: MultipartFormDataContent formDataContent = new MultipartFormDataContent();
  1. 12:  
  1. 13: // Validate the file and add to MultipartFormDataContent object
  1. 14: formDataContent.AddUploadFile(@"c:\nophoto.png");
  1. 15: formDataContent.AddUploadFile(@"c:\ReadMe.txt");
  1. 16:  
  1. 17: if (!formDataContent.HasContent()) // No files found to be uploaded
  1. 18: {
  1. 19: Console.ForegroundColor = ConsoleColor.Red;
  1. 20: Console.Write(formDataContent.GetUploadFileErrorMesage());
  1. 21: return;
  1. 22: }
  1. 23: else
  1. 24: {
  1. 25: string uploadErrorMessage = formDataContent.GetUploadFileErrorMesage();
  1. 26: if (!string.IsNullOrWhiteSpace(uploadErrorMessage)) // Some files couldn't be found
  1. 27: {
  1. 28: Console.ForegroundColor = ConsoleColor.Red;
  1. 29: Console.Write(uploadErrorMessage);
  1. 30: }
  1. 31:  
  1. 32: HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uploadRequestURI);
  1. 33: request.Content = formDataContent;
  1. 34:  
  1. 35: using (HttpClient httpClient = new HttpClient())
  1. 36: {
  1. 37: Console.ForegroundColor = ConsoleColor.Green;
  1. 38: Console.WriteLine(string.Format("Start uploading @ {0}, {1} time ",
  1. 39: DateTime.Now.ToLongDateString(),
  1. 40: DateTime.Now.ToLongTimeString()));
  1. 41:  
  1. 42: httpClient.BaseAddress = baseStreamingURL;
  1. 43: await httpClient.SendAsync(request).
  1. 44: ContinueWith((response)
  1. 45: =>
  1. 46: {
  1. 47: try
  1. 48: {
  1. 49: ProcessUploadResponse(response);
  1. 50: }
  1. 51: catch (AggregateException aggregateException)
  1. 52: {
  1. 53: Console.ForegroundColor = ConsoleColor.Red;
  1. 54: Console.WriteLine(string.Format("Exception : ", aggregateException));
  1. 55: }
  1. 56: });
  1. 57: }
  1. 58: }
  1. 59: }
  1. 60: catch (Exception ex)
  1. 61: {
  1. 62: Console.ForegroundColor = ConsoleColor.Red;
  1. 63: Console.WriteLine(ex.Message);
  1. 64: }
  1. 65: }
  1. 66:  
  1. 67: /// <summary>
  1. 68: /// Process download response object
  1. 69: /// </summary>
  1. 70: /// <param name="response">Awaitable HttpResponseMessage task value</param>
  1. 71: private static void ProcessUploadResponse(Task<HttpResponseMessage> response)
  1. 72: {
  1. 73: if (response.Result.IsSuccessStatusCode)
  1. 74: {
  1. 75: string uploadMessage = string.Format("\nUpload completed @ {0}, {1} time ",
  1. 76: DateTime.Now.ToLongDateString(),
  1. 77: DateTime.Now.ToLongTimeString());
  1. 78: Console.ForegroundColor = ConsoleColor.Green;
  1. 79: Console.WriteLine(string.Format("{0}\nUpload Message : \n{1}", uploadMessage,
  1. 80: JsonConvert.SerializeObject(response.Result.Content.ReadAsAsync<List<FileResponseMessage>>().TryResult(), Formatting.Indented)));
  1. 81: }
  1. 82: else
  1. 83: {
  1. 84: ProcessFailResponse(response);
  1. 85: }
  1. 86: }

数据流项目由可扩展类和方法组成,本文就不再详述。下篇文章中将介绍“使用HTTPS 开发项目”

下载源代码

原文链接:http://www.codeproject.com/Articles/838274/Web-API-Thoughts-of-Data-Streaming#Hist

Web API 数据流使用的更多相关文章

  1. ASP.NET Web API 应用教程(一) ——数据流使用

    相信已经有很多文章来介绍ASP.Net Web API 技术,本系列文章主要介绍如何使用数据流,HTTPS,以及可扩展的Web API 方面的技术,系列文章主要有三篇内容. 主要内容如下: I  数据 ...

  2. Web API与文件操作

    前段时间,一直有练习ASP.NET MVC与Web API交互,接下来,Insus.NET再做一些相关的练习,Web API与文件操作,如POST文件至Web API,更新或是删除等. 不管怎样,先在 ...

  3. OAuth2 for asp.net web api

    在上篇文章中我研究了OpenId及DotNetOpenAuth的相关应用,这一篇继续研究OAuth2. https://github.com/DotNetOpenAuth http://www.cnb ...

  4. ASP.NET MVC和Web API中的Angular2 - 第1部分

    下载源码 - 903.5 KB 内容 第1部分:Visual Studio 2017中的Angular2设置,基本CRUD应用程序,第三方模态弹出控件 第2部分:使用Angular2管道进行过滤/搜索 ...

  5. .NET WEB API关键过程 思维导图

    背景说明 近期在去面试的过程中,被问及有关WEB API的一些特性,一时竟不知该如何回答,故根据自己已知的知识,加上网上搜索的,详细列举了一下,期望对WEB API有一个比较开阔和全面的认知. 关键要 ...

  6. 在一个空ASP.NET Web项目上创建一个ASP.NET Web API 2.0应用

    由于ASP.NET Web API具有与ASP.NET MVC类似的编程方式,再加上目前市面上专门介绍ASP.NET Web API 的书籍少之又少(我们看到的相关内容往往是某本介绍ASP.NET M ...

  7. bootstrap + requireJS+ director+ knockout + web API = 一个时髦的单页程序

    也许单页程序(Single Page Application)并不是什么时髦的玩意,像Gmail在很早之前就已经在使用这种模式.通常的说法是它通过避免页面刷新大大提高了网站的响应性,像操作桌面应用程序 ...

  8. Hello Web API系列教程——Web API与国际化

    软件国际化是在软件设计和文档开发过程中,使得功能和代码设计能处理多种语言和文化习俗,在创建不同语言版本时,不需要重新设计源程序代码的软件工程方法.这在很多成熟的软件开发平台中非常常见.对于.net开发 ...

  9. ASP.NET Web API 跨域访问(CORS)

    一.客户端用JSONP请求数据 如果你想用JSONP来获得跨域的数据,WebAPI本身是不支持javascript的callback的,它返回的JSON是这样的: {"YourSignatu ...

随机推荐

  1. html练习(5)

    这个练习主要简单的展示了据对定位和相对定位: 在此说下html的定位: 1.static定位 这个是默认的方式.对static而言.left和right是不生效的. 2.relative定位(相对定位 ...

  2. exit()和_exit()和return

    exit()和return的差别: 依照ANSI C,在最初调用的main()中使用return和exit()的效果同样. 但要注意这里所说的是"最初调用".假设main()在一个 ...

  3. ubuntu配置jdk脚本以及导致开不了机的解决方案

    关于在那个文件里配置jdk脚本,有些大牛总结了四个地方,大体就是ubuntu系统启动后会默认加载的四个地方.例如:/etcenvironment,/etc/profile这两个文件处于系统层面的,还有 ...

  4. RSD和wlwmanifest是什么

    今天小博发现header.php文件里<?php wp_head(); ?>显示有以下的两句代码,因为小博的网站打开速度实在太慢了,换空间怕麻烦,那就只有优化代码了. <link r ...

  5. hdu2159(二维完全背包)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2159 题意:打怪,还有最后一级,忍耐度有限m,问在杀怪数量上限为s的情况下能否获取n经验而通关,且忍耐 ...

  6. Android -&gt; 怎样避免Handler引起内存泄露

    很多其它内容,可訪问个人博客www.liangfeizc.com 错误代码 假设在Activiy中通过内部类(Runnable)的方式定义了一个变量runnable, final Runnable r ...

  7. 2014ACM/ICPC亚洲区西安站 F题 color (组合数学,容斥原理)

    题目链接:传送门 题意: n个格子排成一行.我们有m种颜色.能够给这些格子涂色,保证相邻的格子的颜色不同 问,最后恰好使用了k种颜色的方案数. 分析: 看完题目描写叙述之后立刻想到了一个公式 :C(m ...

  8. gem5 设定checkpiont以及从checkpoint开始运行

    同spec2006中间bzip2一个例子,如何设置checkpoint .以及从checkpoint继续以启动运行.这样做的目的是为了,采纳automic运行N指令,然后detailed运行M指令. ...

  9. hdu4714(树形dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4714 题意:给你一棵树,,其中每去掉一条边或加一条边的代价均为1,让你求出将其变成一个圆的最小代价. ...

  10. java设计模式_单例

    public class Singleton { public static void main(String[] args) throws Exception { System.out.printl ...